Skip to content

Commit

Permalink
Fix socket reading function for TCP (non-HTTPS) connections on Windows
Browse files Browse the repository at this point in the history
Signed-off-by: Joffrey F <joffrey@docker.com>
  • Loading branch information
shin- committed Jun 7, 2018
1 parent 49bb738 commit dbe52dc
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
3 changes: 3 additions & 0 deletions docker/utils/socket.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import errno
import os
import select
import socket as pysocket
import struct

import six
Expand Down Expand Up @@ -28,6 +29,8 @@ def read(socket, n=4096):
try:
if hasattr(socket, 'recv'):
return socket.recv(n)
if six.PY3 and isinstance(socket, getattr(pysocket, 'SocketIO')):
return socket.read(n)
return os.read(socket.fileno(), n)
except EnvironmentError as e:
if e.errno not in recoverable_errors:
Expand Down
58 changes: 56 additions & 2 deletions tests/unit/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def test_stream_helper_decoding(self):
assert result == content


class StreamTest(unittest.TestCase):
class UnixSocketStreamTest(unittest.TestCase):
def setUp(self):
socket_dir = tempfile.mkdtemp()
self.build_context = tempfile.mkdtemp()
Expand Down Expand Up @@ -462,7 +462,61 @@ def test_early_stream_response(self):
raise e

assert list(stream) == [
str(i).encode() for i in range(50)]
str(i).encode() for i in range(50)
]


class TCPSocketStreamTest(unittest.TestCase):
text_data = b'''
Now, those children out there, they're jumping through the
flames in the hope that the god of the fire will make them fruitful.
Really, you can't blame them. After all, what girl would not prefer the
child of a god to that of some acne-scarred artisan?
'''

def setUp(self):

self.server = six.moves.socketserver.ThreadingTCPServer(
('', 0), self.get_handler_class()
)
self.thread = threading.Thread(target=self.server.serve_forever)
self.thread.setDaemon(True)
self.thread.start()
self.address = 'http://{}:{}'.format(
socket.gethostname(), self.server.server_address[1]
)

def tearDown(self):
self.server.shutdown()
self.server.server_close()
self.thread.join()

def get_handler_class(self):
text_data = self.text_data

class Handler(six.moves.BaseHTTPServer.BaseHTTPRequestHandler, object):
def do_POST(self):
self.send_response(101)
self.send_header(
'Content-Type', 'application/vnd.docker.raw-stream'
)
self.send_header('Connection', 'Upgrade')
self.send_header('Upgrade', 'tcp')
self.end_headers()
self.wfile.flush()
time.sleep(0.2)
self.wfile.write(text_data)
self.wfile.flush()

return Handler

def test_read_from_socket(self):
with APIClient(base_url=self.address) as client:
resp = client._post(client._url('/dummy'), stream=True)
data = client._read_from_socket(resp, stream=True, tty=True)
results = b''.join(data)

assert results == self.text_data


class UserAgentTest(unittest.TestCase):
Expand Down

0 comments on commit dbe52dc

Please sign in to comment.