From 37983921c90b468cafd3ba2ca2574fb81cafe5a7 Mon Sep 17 00:00:00 2001 From: Jim Minter Date: Wed, 7 Mar 2018 13:23:03 -0500 Subject: [PATCH] Ensure a hijacked connection implements CloseWrite whenever its underlying connection does. If this isn't done, then a container listening on stdin won't receive an EOF when the client closes the stream at their end. Signed-off-by: Jim Minter --- client/hijack.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/client/hijack.go b/client/hijack.go index 628adfda65..5a6354561b 100644 --- a/client/hijack.go +++ b/client/hijack.go @@ -188,8 +188,14 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e c, br := clientconn.Hijack() if br.Buffered() > 0 { - // If there is buffered content, wrap the connection - c = &hijackedConn{c, br} + // If there is buffered content, wrap the connection. We return an + // object that implements CloseWrite iff the underlying connection + // implements it. + if _, ok := c.(types.CloseWriter); ok { + c = &hijackedConnCloseWriter{c, br} + } else { + c = &hijackedConn{c, br} + } } else { br.Reset(nil) } @@ -197,6 +203,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e return c, nil } +// hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case +// that a) there was already buffered data in the http layer when Hijack() was +// called, and b) the underlying net.Conn does *not* implement CloseWrite(). +// hijackedConn does not implement CloseWrite() either. type hijackedConn struct { net.Conn r *bufio.Reader @@ -205,3 +215,16 @@ type hijackedConn struct { func (c *hijackedConn) Read(b []byte) (int, error) { return c.r.Read(b) } + +// hijackedConnCloseWriter is a hijackedConn which additionally implements +// CloseWrite(). It is returned by setupHijackConn in the case that a) there +// was already buffered data in the http layer when Hijack() was called, and b) +// the underlying net.Conn *does* implement CloseWrite(). +type hijackedConnCloseWriter hijackedConn + +var _ types.CloseWriter = &hijackedConnCloseWriter{} + +func (c *hijackedConnCloseWriter) CloseWrite() error { + conn := c.Conn.(types.CloseWriter) + return conn.CloseWrite() +}