diff --git a/requests_unixsocket/__init__.py b/requests_unixsocket/__init__.py index b3ba152..0fb5e1f 100644 --- a/requests_unixsocket/__init__.py +++ b/requests_unixsocket/__init__.py @@ -3,8 +3,6 @@ import sys from .adapters import UnixAdapter -__all__ = ['monkeypatch', 'Session'] - DEFAULT_SCHEME = 'http+unix://' @@ -18,10 +16,17 @@ class monkeypatch(object): def __init__(self, url_scheme=DEFAULT_SCHEME): self.session = Session() requests = self._get_global_requests_module() - self.orig_requests_get = requests.get - requests.get = self.session.get - self.orig_requests_request = requests.request - requests.request = self.session.request + + # Methods to replace + self.methods = ('request', 'get', 'head', 'post', + 'patch', 'put', 'delete', 'options') + # Store the original methods + self.orig_methods = dict( + (m, requests.__dict__[m]) for m in self.methods) + # Monkey patch + g = globals() + for m in self.methods: + requests.__dict__[m] = g[m] def _get_global_requests_module(self): return sys.modules['requests'] @@ -31,5 +36,42 @@ class monkeypatch(object): def __exit__(self, *args): requests = self._get_global_requests_module() - requests.get = self.orig_requests_get - requests.request = self.orig_requests_request + for m in self.methods: + requests.__dict__[m] = self.orig_methods[m] + + +# These are the same methods defined for the global requests object +def request(method, url, **kwargs): + session = Session() + return session.request(method=method, url=url, **kwargs) + + +def get(url, **kwargs): + kwargs.setdefault('allow_redirects', True) + return request('get', url, **kwargs) + + +def head(url, **kwargs): + kwargs.setdefault('allow_redirects', False) + return request('head', url, **kwargs) + + +def post(url, data=None, json=None, **kwargs): + return request('post', url, data=data, json=json, **kwargs) + + +def patch(url, data=None, **kwargs): + return request('patch', url, data=data, **kwargs) + + +def put(url, data=None, **kwargs): + return request('put', url, data=data, **kwargs) + + +def delete(url, **kwargs): + return request('delete', url, **kwargs) + + +def options(url, **kwargs): + kwargs.setdefault('allow_redirects', True) + return request('options', url, **kwargs) diff --git a/requests_unixsocket/adapters.py b/requests_unixsocket/adapters.py index 356d59d..8449b86 100644 --- a/requests_unixsocket/adapters.py +++ b/requests_unixsocket/adapters.py @@ -13,6 +13,7 @@ except ImportError: # The following was adapted from some code from docker-py # https://github.com/docker/docker-py/blob/master/docker/unixconn/unixconn.py class UnixHTTPConnection(HTTPConnection): + def __init__(self, unix_socket_url, timeout=60): """Create an HTTP connection to a unix domain socket @@ -33,6 +34,7 @@ class UnixHTTPConnection(HTTPConnection): class UnixHTTPConnectionPool(HTTPConnectionPool): + def __init__(self, socket_path, timeout=60): HTTPConnectionPool.__init__(self, 'localhost', timeout=timeout) self.socket_path = socket_path @@ -43,12 +45,16 @@ class UnixHTTPConnectionPool(HTTPConnectionPool): class UnixAdapter(HTTPAdapter): + def __init__(self, timeout=60): super(UnixAdapter, self).__init__() self.timeout = timeout def get_connection(self, socket_path, proxies=None): - if proxies: + proxies = proxies or {} + proxy = proxies.get(urlparse(socket_path.lower()).scheme) + + if proxy: raise ValueError('%s does not support specifying proxies' % self.__class__.__name__) return UnixHTTPConnectionPool(socket_path, self.timeout) diff --git a/requests_unixsocket/tests/test_requests_unixsocket.py b/requests_unixsocket/tests/test_requests_unixsocket.py index 81b3fdf..34151b2 100755 --- a/requests_unixsocket/tests/test_requests_unixsocket.py +++ b/requests_unixsocket/tests/test_requests_unixsocket.py @@ -20,67 +20,11 @@ def test_unix_domain_adapter_ok(): session = requests_unixsocket.Session('http+unix://') urlencoded_usock = requests.compat.quote_plus(usock_thread.usock) url = 'http+unix://%s/path/to/page' % urlencoded_usock - logger.debug('Calling session.get(%r) ...', url) - r = session.get(url) - logger.debug( - 'Received response: %r with text: %r and headers: %r', - r, r.text, r.headers) - assert r.status_code == 200 - assert r.headers['server'] == 'waitress' - assert r.headers['X-Transport'] == 'unix domain socket' - assert r.headers['X-Requested-Path'] == '/path/to/page' - assert r.headers['X-Socket-Path'] == usock_thread.usock - assert isinstance(r.connection, requests_unixsocket.UnixAdapter) - assert r.url == url - assert r.text == 'Hello world!' - -def test_unix_domain_adapter_url_with_query_params(): - with UnixSocketServerThread() as usock_thread: - session = requests_unixsocket.Session('http+unix://') - urlencoded_usock = requests.compat.quote_plus(usock_thread.usock) - url = ('http+unix://%s' - '/containers/nginx/logs?timestamp=true' % urlencoded_usock) - logger.debug('Calling session.get(%r) ...', url) - r = session.get(url) - logger.debug( - 'Received response: %r with text: %r and headers: %r', - r, r.text, r.headers) - assert r.status_code == 200 - assert r.headers['server'] == 'waitress' - assert r.headers['X-Transport'] == 'unix domain socket' - assert r.headers['X-Requested-Path'] == '/containers/nginx/logs' - assert r.headers['X-Requested-Query-String'] == 'timestamp=true' - assert r.headers['X-Socket-Path'] == usock_thread.usock - assert isinstance(r.connection, requests_unixsocket.UnixAdapter) - assert r.url == url - assert r.text == 'Hello world!' - - -def test_unix_domain_adapter_connection_error(): - session = requests_unixsocket.Session('http+unix://') - - with pytest.raises(requests.ConnectionError): - session.get('http+unix://socket_does_not_exist/path/to/page') - - -def test_unix_domain_adapter_connection_proxies_error(): - session = requests_unixsocket.Session('http+unix://') - - with pytest.raises(ValueError) as excinfo: - session.get('http+unix://socket_does_not_exist/path/to/page', - proxies={"http": "http://10.10.1.10:1080"}) - assert ('UnixAdapter does not support specifying proxies' - in str(excinfo.value)) - - -def test_unix_domain_adapter_monkeypatch(): - with UnixSocketServerThread() as usock_thread: - with requests_unixsocket.monkeypatch('http+unix://'): - urlencoded_usock = requests.compat.quote_plus(usock_thread.usock) - url = 'http+unix://%s/path/to/page' % urlencoded_usock - logger.debug('Calling requests.get(%r) ...', url) - r = requests.get(url) + for method in ['get', 'post', 'head', 'patch', 'put', 'delete', + 'options']: + logger.debug('Calling session.%s(%r) ...', method, url) + r = getattr(session, method)(url) logger.debug( 'Received response: %r with text: %r and headers: %r', r, r.text, r.headers) @@ -91,7 +35,87 @@ def test_unix_domain_adapter_monkeypatch(): assert r.headers['X-Socket-Path'] == usock_thread.usock assert isinstance(r.connection, requests_unixsocket.UnixAdapter) assert r.url == url - assert r.text == 'Hello world!' + if method == 'head': + assert r.text == '' + else: + assert r.text == 'Hello world!' + +def test_unix_domain_adapter_url_with_query_params(): + with UnixSocketServerThread() as usock_thread: + session = requests_unixsocket.Session('http+unix://') + urlencoded_usock = requests.compat.quote_plus(usock_thread.usock) + url = ('http+unix://%s' + '/containers/nginx/logs?timestamp=true' % urlencoded_usock) + + for method in ['get', 'post', 'head', 'patch', 'put', 'delete', + 'options']: + logger.debug('Calling session.%s(%r) ...', method, url) + r = getattr(session, method)(url) + logger.debug( + 'Received response: %r with text: %r and headers: %r', + r, r.text, r.headers) + assert r.status_code == 200 + assert r.headers['server'] == 'waitress' + assert r.headers['X-Transport'] == 'unix domain socket' + assert r.headers['X-Requested-Path'] == '/containers/nginx/logs' + assert r.headers['X-Requested-Query-String'] == 'timestamp=true' + assert r.headers['X-Socket-Path'] == usock_thread.usock + assert isinstance(r.connection, requests_unixsocket.UnixAdapter) + assert r.url == url + if method == 'head': + assert r.text == '' + else: + assert r.text == 'Hello world!' + + +def test_unix_domain_adapter_connection_error(): + session = requests_unixsocket.Session('http+unix://') + + for method in ['get', 'post', 'head', 'patch', 'put', 'delete', 'options']: + with pytest.raises(requests.ConnectionError): + getattr(session, method)( + 'http+unix://socket_does_not_exist/path/to/page') + + +def test_unix_domain_adapter_connection_proxies_error(): + session = requests_unixsocket.Session('http+unix://') + + for method in ['get', 'post', 'head', 'patch', 'put', 'delete', 'options']: + with pytest.raises(ValueError) as excinfo: + getattr(session, method)( + 'http+unix://socket_does_not_exist/path/to/page', + proxies={"http+unix": "http://10.10.1.10:1080"}) + assert ('UnixAdapter does not support specifying proxies' + in str(excinfo.value)) + + +def test_unix_domain_adapter_monkeypatch(): + with UnixSocketServerThread() as usock_thread: + with requests_unixsocket.monkeypatch('http+unix://'): + urlencoded_usock = requests.compat.quote_plus(usock_thread.usock) + url = 'http+unix://%s/path/to/page' % urlencoded_usock + + for method in ['get', 'post', 'head', 'patch', 'put', 'delete', + 'options']: + logger.debug('Calling session.%s(%r) ...', method, url) + r = getattr(requests, method)(url) + logger.debug( + 'Received response: %r with text: %r and headers: %r', + r, r.text, r.headers) + assert r.status_code == 200 + assert r.headers['server'] == 'waitress' + assert r.headers['X-Transport'] == 'unix domain socket' + assert r.headers['X-Requested-Path'] == '/path/to/page' + assert r.headers['X-Socket-Path'] == usock_thread.usock + assert isinstance(r.connection, + requests_unixsocket.UnixAdapter) + assert r.url == url + if method == 'head': + assert r.text == '' + else: + assert r.text == 'Hello world!' + + for method in ['get', 'post', 'head', 'patch', 'put', 'delete', 'options']: with pytest.raises(requests.exceptions.InvalidSchema): - requests.get(url) + getattr(requests, method)(url)