Browse code

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 <jminter@redhat.com>

Jim Minter authored on 2018/03/08 03:23:03
Showing 1 changed files
... ...
@@ -188,8 +188,14 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e
188 188
 
189 189
 	c, br := clientconn.Hijack()
190 190
 	if br.Buffered() > 0 {
191
-		// If there is buffered content, wrap the connection
192
-		c = &hijackedConn{c, br}
191
+		// If there is buffered content, wrap the connection.  We return an
192
+		// object that implements CloseWrite iff the underlying connection
193
+		// implements it.
194
+		if _, ok := c.(types.CloseWriter); ok {
195
+			c = &hijackedConnCloseWriter{c, br}
196
+		} else {
197
+			c = &hijackedConn{c, br}
198
+		}
193 199
 	} else {
194 200
 		br.Reset(nil)
195 201
 	}
... ...
@@ -197,6 +203,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e
197 197
 	return c, nil
198 198
 }
199 199
 
200
+// hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case
201
+// that a) there was already buffered data in the http layer when Hijack() was
202
+// called, and b) the underlying net.Conn does *not* implement CloseWrite().
203
+// hijackedConn does not implement CloseWrite() either.
200 204
 type hijackedConn struct {
201 205
 	net.Conn
202 206
 	r *bufio.Reader
... ...
@@ -205,3 +215,16 @@ type hijackedConn struct {
205 205
 func (c *hijackedConn) Read(b []byte) (int, error) {
206 206
 	return c.r.Read(b)
207 207
 }
208
+
209
+// hijackedConnCloseWriter is a hijackedConn which additionally implements
210
+// CloseWrite().  It is returned by setupHijackConn in the case that a) there
211
+// was already buffered data in the http layer when Hijack() was called, and b)
212
+// the underlying net.Conn *does* implement CloseWrite().
213
+type hijackedConnCloseWriter hijackedConn
214
+
215
+var _ types.CloseWriter = &hijackedConnCloseWriter{}
216
+
217
+func (c *hijackedConnCloseWriter) CloseWrite() error {
218
+	conn := c.Conn.(types.CloseWriter)
219
+	return conn.CloseWrite()
220
+}