@@ -11,6 +11,15 @@ import (
1111 "net/url"
1212)
1313
14+ type connWithBufferedReader struct {
15+ net.Conn
16+ r * bufio.Reader
17+ }
18+
19+ func (c * connWithBufferedReader ) Read (p []byte ) (int , error ) {
20+ return c .r .Read (p )
21+ }
22+
1423// withProxyTransport modifies the given transport to handle proxying of unix, socks5 and http connections.
1524//
1625// Note: baseTransport is considered to be a clone created with transport.Clone()
@@ -82,18 +91,22 @@ func withProxyTransport(baseTransport *http.Transport, proxyURL *url.URL, proxyP
8291 return nil , err
8392 }
8493
85- // Read and check the response from the proxy
86- resp , err := http .ReadResponse (bufio . NewReader ( conn ) , nil )
94+ br := bufio . NewReader ( conn )
95+ resp , err := http .ReadResponse (br , nil )
8796 if err != nil {
8897 conn .Close ()
8998 return nil , err
9099 }
91100 if resp .StatusCode != http .StatusOK {
101+ // For non-200, it's safe/appropriate to close the body (it’s a real response body here).
102+ // Try to read a bit (4k bytes) to include in the error message.
103+ b , _ := io .ReadAll (io .LimitReader (resp .Body , 4 << 10 ))
104+ resp .Body .Close ()
92105 conn .Close ()
93- return nil , fmt .Errorf ("failed to connect to proxy %v : %v " , proxyURL , resp .Status )
106+ return nil , fmt .Errorf ("failed to connect to proxy %s : %s: %q " , proxyURL . Redacted () , resp .Status , b )
94107 }
95- resp .Body .Close ()
96- return conn , nil
108+ // 200 CONNECT: do NOT resp.Body.Close(); it would interfere with the tunnel.
109+ return & connWithBufferedReader { Conn : conn , r : br } , nil
97110 }
98111 dialTLS := func (ctx context.Context , network , addr string ) (net.Conn , error ) {
99112 // Dial the underlying connection through the proxy
0 commit comments