Переглянути джерело

Replace use of httputil in client hijack

Simplify the hijack process by just performing the http request/response
on the connection and returning the raw conn after success. The client
conn from httputil is deprecated and easily replaced.

Signed-off-by: Derek McGowan <derek@mcg.dev>
Derek McGowan 1 рік тому
батько
коміт
bb4e9c72d7
1 змінених файлів з 26 додано та 20 видалено
  1. 26 20
      client/hijack.go

+ 26 - 20
client/hijack.go

@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
-	"net/http/httputil"
 	"net/url"
 	"net/url"
 	"time"
 	"time"
 
 
@@ -81,6 +80,11 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn,
 	if err != nil {
 	if err != nil {
 		return nil, "", errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
 		return nil, "", errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
 	}
 	}
+	defer func() {
+		if retErr != nil {
+			conn.Close()
+		}
+	}()
 
 
 	// When we set up a TCP connection for hijack, there could be long periods
 	// When we set up a TCP connection for hijack, there could be long periods
 	// of inactivity (a long running command with no output) that in certain
 	// of inactivity (a long running command with no output) that in certain
@@ -92,11 +96,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn,
 		_ = tcpConn.SetKeepAlivePeriod(30 * time.Second)
 		_ = tcpConn.SetKeepAlivePeriod(30 * time.Second)
 	}
 	}
 
 
-	clientconn := httputil.NewClientConn(conn, nil)
-	defer clientconn.Close()
+	hc := &hijackedConn{conn, bufio.NewReader(conn)}
 
 
 	// Server hijacks the connection, error 'connection closed' expected
 	// Server hijacks the connection, error 'connection closed' expected
-	resp, err := clientconn.Do(req)
+	resp, err := hc.RoundTrip(req)
 	if resp != nil {
 	if resp != nil {
 		// This is a simplified variant of "httpconv.ClientStatus(resp.StatusCode))";
 		// This is a simplified variant of "httpconv.ClientStatus(resp.StatusCode))";
 		//
 		//
@@ -121,29 +124,25 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn,
 		span.SetStatus(code, "")
 		span.SetStatus(code, "")
 	}
 	}
 
 
-	//nolint:staticcheck // ignore SA1019 for connecting to old (pre go1.8) daemons
-	if err != httputil.ErrPersistEOF {
-		if err != nil {
-			return nil, "", err
-		}
-		if resp.StatusCode != http.StatusSwitchingProtocols {
-			_ = resp.Body.Close()
-			return nil, "", fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode)
-		}
+	if err != nil {
+		return nil, "", err
+	}
+	if resp.StatusCode != http.StatusSwitchingProtocols {
+		_ = resp.Body.Close()
+		return nil, "", fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode)
 	}
 	}
 
 
-	c, br := clientconn.Hijack()
-	if br.Buffered() > 0 {
+	if hc.r.Buffered() > 0 {
 		// If there is buffered content, wrap the connection.  We return an
 		// If there is buffered content, wrap the connection.  We return an
 		// object that implements CloseWrite if the underlying connection
 		// object that implements CloseWrite if the underlying connection
 		// implements it.
 		// implements it.
-		if _, ok := c.(types.CloseWriter); ok {
-			c = &hijackedConnCloseWriter{&hijackedConn{c, br}}
+		if _, ok := hc.Conn.(types.CloseWriter); ok {
+			conn = &hijackedConnCloseWriter{hc}
 		} else {
 		} else {
-			c = &hijackedConn{c, br}
+			conn = hc
 		}
 		}
 	} else {
 	} else {
-		br.Reset(nil)
+		hc.r.Reset(nil)
 	}
 	}
 
 
 	var mediaType string
 	var mediaType string
@@ -152,7 +151,7 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn,
 		mediaType = resp.Header.Get("Content-Type")
 		mediaType = resp.Header.Get("Content-Type")
 	}
 	}
 
 
-	return c, mediaType, nil
+	return conn, mediaType, nil
 }
 }
 
 
 // hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case
 // hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case
@@ -164,6 +163,13 @@ type hijackedConn struct {
 	r *bufio.Reader
 	r *bufio.Reader
 }
 }
 
 
+func (c *hijackedConn) RoundTrip(req *http.Request) (*http.Response, error) {
+	if err := req.Write(c.Conn); err != nil {
+		return nil, err
+	}
+	return http.ReadResponse(c.r, req)
+}
+
 func (c *hijackedConn) Read(b []byte) (int, error) {
 func (c *hijackedConn) Read(b []byte) (int, error) {
 	return c.r.Read(b)
 	return c.r.Read(b)
 }
 }