Skip to content

Commit 047c67b

Browse files
cjh1shin-
authored andcommitted
Prevent data loss when attaching to container
The use of buffering within httplib.HTTPResponse can cause data to be lost. socket.makefile() is called without a bufsize, which causes a buffer to be used when recieving data. The attach methods do a HTTP upgrade to tcp before the raw socket is using to stream data from the container. The problem is that if the container starts stream data while httplib/http.client is reading the response to the attach request part of the data ends will end up in the buffer of fileobject created within the HTTPResponse object. This data is lost as after the attach request data is read directly from the raw socket. Signed-off-by: Chris Harris <[email protected]>
1 parent 114512a commit 047c67b

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

docker/transport/unixconn.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ def connect(self):
3434
self.sock = sock
3535

3636

37+
class AttachHTTPResponse(httplib.HTTPResponse):
38+
'''
39+
A HTTPResponse object that doesn't use a buffered fileobject.
40+
'''
41+
def __init__(self, sock, *args, **kwargs):
42+
# Delegate to super class
43+
httplib.HTTPResponse.__init__(self, sock, *args, **kwargs)
44+
45+
# Override fp with a fileobject that doesn't buffer
46+
self.fp = sock.makefile('rb', 0)
47+
48+
49+
class AttachUnixHTTPConnection(UnixHTTPConnection):
50+
'''
51+
A HTTPConnection that returns responses that don't used buffering.
52+
'''
53+
response_class = AttachHTTPResponse
54+
55+
3756
class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
3857
def __init__(self, base_url, socket_path, timeout=60, maxsize=10):
3958
super(UnixHTTPConnectionPool, self).__init__(
@@ -44,9 +63,17 @@ def __init__(self, base_url, socket_path, timeout=60, maxsize=10):
4463
self.timeout = timeout
4564

4665
def _new_conn(self):
47-
return UnixHTTPConnection(
48-
self.base_url, self.socket_path, self.timeout
49-
)
66+
# Special case for attach url, as we do a http upgrade to tcp and
67+
# a buffered connection can cause data loss.
68+
path = urllib3.util.parse_url(self.base_url).path
69+
if path.endswith('attach'):
70+
return AttachUnixHTTPConnection(
71+
self.base_url, self.socket_path, self.timeout
72+
)
73+
else:
74+
return UnixHTTPConnection(
75+
self.base_url, self.socket_path, self.timeout
76+
)
5077

5178

5279
class UnixAdapter(requests.adapters.HTTPAdapter):

0 commit comments

Comments
 (0)