11package api
22
33import (
4- "bufio"
54 "context"
65 "crypto/tls"
7- "encoding/base64"
8- "io"
96 "net"
107 "net/http"
118 "net/url"
12-
13- "github.com/sourcegraph/sourcegraph/lib/errors"
149)
1510
1611// proxyDialAddr returns proxyURL.Host with a default port appended if one is
@@ -43,12 +38,6 @@ func withProxyTransport(baseTransport *http.Transport, proxyURL *url.URL, proxyP
4338 if cfg .ServerName == "" {
4439 cfg .ServerName = host
4540 }
46- // Preserve HTTP/2 negotiation to the origin when ForceAttemptHTTP2
47- // is enabled. Without this, the manual TLS handshake would not
48- // advertise h2 via ALPN, silently forcing HTTP/1.1.
49- if baseTransport .ForceAttemptHTTP2 && len (cfg .NextProtos ) == 0 {
50- cfg .NextProtos = []string {"h2" , "http/1.1" }
51- }
5241 tlsConn := tls .Client (conn , cfg )
5342 if err := tlsConn .HandshakeContext (ctx ); err != nil {
5443 tlsConn .Close ()
@@ -74,83 +63,7 @@ func withProxyTransport(baseTransport *http.Transport, proxyURL *url.URL, proxyP
7463 // clear out any system proxy settings
7564 baseTransport .Proxy = nil
7665 } else if proxyURL != nil {
77- switch proxyURL .Scheme {
78- case "http" , "socks5" , "socks5h" :
79- // HTTP and SOCKS proxies work out of the box - no need to manually dial
80- baseTransport .Proxy = http .ProxyURL (proxyURL )
81- case "https" :
82- dial := func (ctx context.Context , network , addr string ) (net.Conn , error ) {
83- // Dial the proxy. For TLS-enabled proxies, we TLS-connect to the
84- // proxy itself and force ALPN to HTTP/1.1 to prevent Go from
85- // negotiating HTTP/2 for the CONNECT tunnel. Many proxy servers
86- // don't support HTTP/2 CONNECT, and Go's default Transport.Proxy
87- // would negotiate h2 via ALPN when TLS-connecting to a TLS-enabled
88- // proxy, causing "bogus greeting" errors. For plain HTTP proxies,
89- // CONNECT is always HTTP/1.1 over plain TCP so this isn't needed.
90- // The target connection (e.g. to sourcegraph.com) still negotiates
91- // HTTP/2 normally through the established tunnel.
92- proxyAddr := proxyDialAddr (proxyURL )
93-
94- raw , dialErr := (& net.Dialer {}).DialContext (ctx , "tcp" , proxyAddr )
95- if dialErr != nil {
96- return nil , dialErr
97- }
98- cfg := baseTransport .TLSClientConfig .Clone ()
99- cfg .NextProtos = []string {"http/1.1" }
100- if cfg .ServerName == "" {
101- cfg .ServerName = proxyURL .Hostname ()
102- }
103- conn := tls .Client (raw , cfg )
104- if err := conn .HandshakeContext (ctx ); err != nil {
105- raw .Close ()
106- return nil , err
107- }
108-
109- connectReq := & http.Request {
110- Method : "CONNECT" ,
111- URL : & url.URL {Opaque : addr },
112- Host : addr ,
113- Header : make (http.Header ),
114- }
115- if proxyURL .User != nil {
116- password , _ := proxyURL .User .Password ()
117- auth := base64 .StdEncoding .EncodeToString ([]byte (proxyURL .User .Username () + ":" + password ))
118- connectReq .Header .Set ("Proxy-Authorization" , "Basic " + auth )
119- }
120- if err := connectReq .Write (conn ); err != nil {
121- conn .Close ()
122- return nil , err
123- }
124-
125- resp , err := http .ReadResponse (bufio .NewReader (conn ), nil )
126- if err != nil {
127- conn .Close ()
128- return nil , err
129- }
130- if resp .StatusCode != http .StatusOK {
131- // For non-200, it's safe/appropriate to close the body (it’s a real response body here).
132- // Try to read a bit (4k bytes) to include in the error message.
133- b , _ := io .ReadAll (io .LimitReader (resp .Body , 4 << 10 ))
134- resp .Body .Close ()
135- conn .Close ()
136- return nil , errors .Newf ("failed to connect to proxy %s: %s: %q" , proxyURL .Redacted (), resp .Status , b )
137- }
138- // 200 CONNECT: do NOT resp.Body.Close(); it would interfere with the tunnel.
139- return conn , nil
140- }
141- dialTLS := func (ctx context.Context , network , addr string ) (net.Conn , error ) {
142- // Dial the underlying connection through the proxy
143- conn , err := dial (ctx , network , addr )
144- if err != nil {
145- return nil , err
146- }
147- return handshakeTLS (ctx , conn , addr )
148- }
149- baseTransport .DialContext = dial
150- baseTransport .DialTLSContext = dialTLS
151- // clear out the system proxy because we're defining our own dialers
152- baseTransport .Proxy = nil
153- }
66+ baseTransport .Proxy = http .ProxyURL (proxyURL )
15467 }
15568
15669 return baseTransport
0 commit comments