Skip to content

Commit e055729

Browse files
committed
Disable buffering based on presence of Connection Upgrade headers
Signed-off-by: Joffrey F <[email protected]>
1 parent 047c67b commit e055729

File tree

2 files changed

+35
-37
lines changed

2 files changed

+35
-37
lines changed

Makefile

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ test: flake8 unit-test unit-test-py3 integration-dind integration-dind-ssl
2727

2828
.PHONY: unit-test
2929
unit-test: build
30-
docker run --rm docker-sdk-python py.test tests/unit
30+
docker run -t --rm docker-sdk-python py.test tests/unit
3131

3232
.PHONY: unit-test-py3
3333
unit-test-py3: build-py3
34-
docker run --rm docker-sdk-python3 py.test tests/unit
34+
docker run -t --rm docker-sdk-python3 py.test tests/unit
3535

3636
.PHONY: integration-test
3737
integration-test: build
38-
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python py.test tests/integration/${file}
38+
docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python py.test -v tests/integration/${file}
3939

4040
.PHONY: integration-test-py3
4141
integration-test-py3: build-py3
42-
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 py.test tests/integration/${file}
42+
docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 py.test tests/integration/${file}
4343

4444
TEST_API_VERSION ?= 1.30
4545
TEST_ENGINE_VERSION ?= 17.06.0-ce
@@ -49,9 +49,9 @@ integration-dind: build build-py3
4949
docker rm -vf dpy-dind || :
5050
docker run -d --name dpy-dind --privileged dockerswarm/dind:${TEST_ENGINE_VERSION} dockerd\
5151
-H tcp://0.0.0.0:2375 --experimental
52-
docker run --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
52+
docker run -t --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
5353
--link=dpy-dind:docker docker-sdk-python py.test tests/integration
54-
docker run --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
54+
docker run -t --rm --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
5555
--link=dpy-dind:docker docker-sdk-python3 py.test tests/integration
5656
docker rm -vf dpy-dind
5757

@@ -63,21 +63,21 @@ integration-dind-ssl: build-dind-certs build build-py3
6363
-v /tmp --privileged dockerswarm/dind:${TEST_ENGINE_VERSION} dockerd --tlsverify\
6464
--tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem\
6565
--tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375 --experimental
66-
docker run --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
66+
docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
6767
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
6868
--link=dpy-dind-ssl:docker docker-sdk-python py.test tests/integration
69-
docker run --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
69+
docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
7070
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
7171
--link=dpy-dind-ssl:docker docker-sdk-python3 py.test tests/integration
7272
docker rm -vf dpy-dind-ssl dpy-dind-certs
7373

7474
.PHONY: flake8
7575
flake8: build
76-
docker run --rm docker-sdk-python flake8 docker tests
76+
docker run -t --rm docker-sdk-python flake8 docker tests
7777

7878
.PHONY: docs
7979
docs: build-docs
80-
docker run --rm -it -v `pwd`:/src docker-sdk-python-docs sphinx-build docs docs/_build
80+
docker run --rm -t -v `pwd`:/src docker-sdk-python-docs sphinx-build docs docs/_build
8181

8282
.PHONY: shell
8383
shell: build

docker/transport/unixconn.py

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,45 @@
1818
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
1919

2020

21+
class UnixHTTPResponse(httplib.HTTPResponse, object):
22+
def __init__(self, sock, *args, **kwargs):
23+
disable_buffering = kwargs.pop('disable_buffering', False)
24+
super(UnixHTTPResponse, self).__init__(sock, *args, **kwargs)
25+
if disable_buffering is True:
26+
# We must first create a new pointer then close the old one
27+
# to avoid closing the underlying socket.
28+
new_fp = sock.makefile('rb', 0)
29+
self.fp.close()
30+
self.fp = new_fp
31+
32+
2133
class UnixHTTPConnection(httplib.HTTPConnection, object):
34+
2235
def __init__(self, base_url, unix_socket, timeout=60):
2336
super(UnixHTTPConnection, self).__init__(
2437
'localhost', timeout=timeout
2538
)
2639
self.base_url = base_url
2740
self.unix_socket = unix_socket
2841
self.timeout = timeout
42+
self.disable_buffering = False
2943

3044
def connect(self):
3145
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
3246
sock.settimeout(self.timeout)
3347
sock.connect(self.unix_socket)
3448
self.sock = sock
3549

50+
def putheader(self, header, *values):
51+
super(UnixHTTPConnection, self).putheader(header, *values)
52+
if header == 'Connection' and 'Upgrade' in values:
53+
self.disable_buffering = True
3654

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-
55+
def response_class(self, sock, *args, **kwargs):
56+
if self.disable_buffering:
57+
kwargs['disable_buffering'] = True
4858

49-
class AttachUnixHTTPConnection(UnixHTTPConnection):
50-
'''
51-
A HTTPConnection that returns responses that don't used buffering.
52-
'''
53-
response_class = AttachHTTPResponse
59+
return UnixHTTPResponse(sock, *args, **kwargs)
5460

5561

5662
class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
@@ -63,17 +69,9 @@ def __init__(self, base_url, socket_path, timeout=60, maxsize=10):
6369
self.timeout = timeout
6470

6571
def _new_conn(self):
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-
)
72+
return UnixHTTPConnection(
73+
self.base_url, self.socket_path, self.timeout
74+
)
7775

7876

7977
class UnixAdapter(requests.adapters.HTTPAdapter):

0 commit comments

Comments
 (0)