From 073b549ff0e2638e9f0e635c94362dd7ff603a35 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Mon, 27 Dec 2021 14:12:27 -0800 Subject: [PATCH 1/2] bug(api)!: remove timeout code BREAKING CHANGE: Remove timeout code and `timeout` parameter from method signatures, because it gives the impression of doing something, but seems to be ineffective (see https://github.com/msabramo/requests-unixsocket/issues/44#issuecomment-1001781097). Sem-Ver: api-break --- requests_unixsocket/adapters.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/requests_unixsocket/adapters.py b/requests_unixsocket/adapters.py index 83e1400..f0e270a 100644 --- a/requests_unixsocket/adapters.py +++ b/requests_unixsocket/adapters.py @@ -18,16 +18,15 @@ # https://github.com/docker/docker-py/blob/master/docker/transport/unixconn.py class UnixHTTPConnection(httplib.HTTPConnection, object): - def __init__(self, unix_socket_url, timeout=60): + def __init__(self, unix_socket_url): """Create an HTTP connection to a unix domain socket :param unix_socket_url: A URL with a scheme of 'http+unix' and the netloc is a percent-encoded path to a unix domain socket. E.g.: 'http+unix://%2Ftmp%2Fprofilesvc.sock/status/pid' """ - super(UnixHTTPConnection, self).__init__('localhost', timeout=timeout) + super(UnixHTTPConnection, self).__init__('localhost') self.unix_socket_url = unix_socket_url - self.timeout = timeout self.sock = None def __del__(self): # base class does not have d'tor @@ -44,21 +43,18 @@ def connect(self): class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool): - def __init__(self, socket_path, timeout=60): - super(UnixHTTPConnectionPool, self).__init__( - 'localhost', timeout=timeout) + def __init__(self, socket_path): + super(UnixHTTPConnectionPool, self).__init__('localhost') self.socket_path = socket_path - self.timeout = timeout def _new_conn(self): - return UnixHTTPConnection(self.socket_path, self.timeout) + return UnixHTTPConnection(self.socket_path) class UnixAdapter(HTTPAdapter): - def __init__(self, timeout=60, pool_connections=25, *args, **kwargs): + def __init__(self, pool_connections=25, *args, **kwargs): super(UnixAdapter, self).__init__(*args, **kwargs) - self.timeout = timeout self.pools = urllib3._collections.RecentlyUsedContainer( pool_connections, dispose_func=lambda p: p.close() ) @@ -76,7 +72,7 @@ def get_connection(self, url, proxies=None): if pool: return pool - pool = UnixHTTPConnectionPool(url, self.timeout) + pool = UnixHTTPConnectionPool(url) self.pools[url] = pool return pool From 44f9fa22c67265181f271f010272ac10383007f6 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Mon, 27 Dec 2021 14:24:55 -0800 Subject: [PATCH 2/2] Add timeout_socket_server.py This is a UNIX domain socket server that accepts connections and never responds, so that we can test timeouts on the client side. --- timeout_socket_server.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 timeout_socket_server.py diff --git a/timeout_socket_server.py b/timeout_socket_server.py new file mode 100644 index 0000000..b9ddaa8 --- /dev/null +++ b/timeout_socket_server.py @@ -0,0 +1,40 @@ +import socket +import time +import os + +server_address = './uds_socket' + +# Make sure the socket does not already exist +try: + os.unlink(server_address) +except OSError: + if os.path.exists(server_address): + raise + +sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +print('starting up on {}'.format(server_address)) +sock.bind(server_address) +sock.listen(1) + +while True: + print('\nwaiting for a connection') + + connection, client_address = sock.accept() + connection.settimeout(300) + + try: + print('connected') + connect_time = time.time() + while True: + try: + data = connection.recv(640) + if not data: + elapsed_time = int(time.time() - connect_time) + print(f'no data after {elapsed_time}s') + break + except socket.timeout as exc: + elapsed_time = int(time.time() - connect_time) + print(f'timeout after {elapsed_time}s on recv') + break + finally: + connection.close()