Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fix socket reading function for TCP (non-HTTPS) connections on Windows
Signed-off-by: Joffrey F <[email protected]>
  • Loading branch information
shin- committed Jun 7, 2018
commit d2520d71abfb7b9e9d4f3f2bfc9657d29b1f34a0
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