Skip to content

Commit d2ca262

Browse files
committed
use http.Request instead of manually building the request, and use Request.Write to ensure correctness
1 parent 7651284 commit d2ca262

1 file changed

Lines changed: 8 additions & 29 deletions

File tree

internal/api/proxy.go

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -66,39 +66,18 @@ func withProxyTransport(baseTransport *http.Transport, proxyURL *url.URL, proxyP
6666
return nil, err
6767
}
6868

69-
// this is the whole point of manually dialing the HTTP(S) proxy:
70-
// being able to force HTTP/1.
71-
// When relying on Transport.Proxy, the protocol is always HTTP/2,
72-
// but many proxy servers don't support HTTP/2.
73-
// We don't want to disable HTTP/2 in general because we want to use it when
74-
// connecting to the Sourcegraph API, using HTTP/1 for the proxy connection only.
75-
protocol := "HTTP/1.1"
76-
77-
// CONNECT is the HTTP method used to set up a tunneling connection with a proxy
78-
method := "CONNECT"
79-
80-
// Manually writing out the HTTP commands because it's not complicated,
81-
// and http.Request has some janky behavior:
82-
// - ignores the Proto field and hard-codes the protocol to HTTP/1.1
83-
// - ignores the Host Header (Header.Set("Host", host)) and uses URL.Host instead.
84-
// - When the Host field is set, overrides the URL field
85-
connectReq := fmt.Sprintf("%s %s %s\r\n", method, addr, protocol)
86-
87-
// A Host header is required per RFC 2616, section 14.23
88-
connectReq += fmt.Sprintf("Host: %s\r\n", addr)
89-
90-
// use authentication if proxy credentials are present
69+
connectReq := &http.Request{
70+
Method: "CONNECT",
71+
URL: &url.URL{Opaque: addr},
72+
Host: addr,
73+
Header: make(http.Header),
74+
}
9175
if proxyURL.User != nil {
9276
password, _ := proxyURL.User.Password()
9377
auth := base64.StdEncoding.EncodeToString([]byte(proxyURL.User.Username() + ":" + password))
94-
connectReq += fmt.Sprintf("Proxy-Authorization: Basic %s\r\n", auth)
78+
connectReq.Header.Set("Proxy-Authorization", "Basic "+auth)
9579
}
96-
97-
// finish up with an extra carriage return + newline, as per RFC 7230, section 3
98-
connectReq += "\r\n"
99-
100-
// Send the CONNECT request to the proxy to establish the tunnel
101-
if _, err := conn.Write([]byte(connectReq)); err != nil {
80+
if err := connectReq.Write(conn); err != nil {
10281
conn.Close()
10382
return nil, err
10483
}

0 commit comments

Comments
 (0)