diff --git a/test/install.py b/test/install.py index 225e109..65262cd 100644 --- a/test/install.py +++ b/test/install.py @@ -1,9 +1,10 @@ +import os import wsgi_intercept class BaseInstalledApp(object): def __init__(self, app, host, port=80, script_name='', - install=None, uninstall=None): + install=None, uninstall=None, proxy=None): self.app = app self.host = host self.port = port @@ -12,6 +13,7 @@ class BaseInstalledApp(object): self._uninstall = uninstall or (lambda: None) self._hits = 0 self._internals = {} + self._proxy = proxy def __call__(self, environ, start_response): self._hits += 1 @@ -32,10 +34,14 @@ class BaseInstalledApp(object): wsgi_intercept.remove_wsgi_intercept(self.host, self.port) def install(self): + if self._proxy: + os.environ['http_proxy'] = self._proxy self._install() self.install_wsgi_intercept() def uninstall(self): + if self._proxy: + del os.environ['http_proxy'] self.uninstall_wsgi_intercept() self._uninstall() @@ -56,9 +62,9 @@ def installer_class(module=None, install=None, uninstall=None): uninstall = uninstall or getattr(module, 'uninstall', None) class InstalledApp(BaseInstalledApp): - def __init__(self, app, host, port=80, script_name=''): + def __init__(self, app, host, port=80, script_name='', proxy=None): BaseInstalledApp.__init__( self, app=app, host=host, port=port, script_name=script_name, - install=install, uninstall=uninstall) + install=install, uninstall=uninstall, proxy=proxy) return InstalledApp diff --git a/test/test_http_client.py b/test/test_http_client.py index 3ca09b4..0622f6e 100644 --- a/test/test_http_client.py +++ b/test/test_http_client.py @@ -42,6 +42,18 @@ def test_other(): assert app.success() +def test_proxy_handling(): + """Proxy variable no impact.""" + with InstalledApp(wsgi_app.simple_app, host=HOST, port=80, + proxy='some.host:1234') as app: + http_client = http_lib.HTTPConnection(HOST) + http_client.request('GET', '/') + content = http_client.getresponse().read() + http_client.close() + assert content == b'WSGI intercept successful!\n' + assert app.success() + + def test_app_error(): with InstalledApp(wsgi_app.raises_app, host=HOST, port=80): http_client = http_lib.HTTPConnection(HOST) diff --git a/test/test_httplib2.py b/test/test_httplib2.py index 9fa91d1..9a67e28 100644 --- a/test/test_httplib2.py +++ b/test/test_httplib2.py @@ -47,6 +47,17 @@ def test_bogus_domain(): 'httplib2_intercept.HTTP_WSGIInterceptorWithTimeout("_nonexistant_domain_").connect()') +def test_proxy_handling(): + """Proxy has no impact.""" + with InstalledApp(wsgi_app.simple_app, host=HOST, port=80, + proxy='some_proxy.com:1234') as app: + http = httplib2.Http() + resp, content = http.request( + 'http://some_hopefully_nonexistant_domain:80/') + assert content == b'WSGI intercept successful!\n' + assert app.success() + + def test_https(): with InstalledApp(wsgi_app.simple_app, host=HOST, port=443) as app: http = httplib2.Http() diff --git a/test/test_requests.py b/test/test_requests.py index 304d178..8005f93 100644 --- a/test/test_requests.py +++ b/test/test_requests.py @@ -1,3 +1,4 @@ +import os import py.test from wsgi_intercept import requests_intercept, WSGIAppError from test import wsgi_app @@ -40,6 +41,18 @@ def test_bogus_domain(): 'requests.get("http://_nonexistant_domain_")') +def test_proxy_handling(): + with py.test.raises(RuntimeError) as exc: + with InstalledApp(wsgi_app.simple_app, host=HOST, port=80, + proxy='some_proxy.com:1234'): + requests.get('http://some_hopefully_nonexistant_domain:80/') + assert 'http_proxy or https_proxy set in environment' in str(exc.value) + # We need to do this by hand because the exception was raised + # during the entry of the context manager, so the exit handler + # wasn't reached. + del os.environ['http_proxy'] + + def test_https(): with InstalledApp(wsgi_app.simple_app, host=HOST, port=443) as app: resp = requests.get('https://some_hopefully_nonexistant_domain:443/') diff --git a/test/test_urllib.py b/test/test_urllib.py index 82daff7..83d793f 100644 --- a/test/test_urllib.py +++ b/test/test_urllib.py @@ -1,3 +1,4 @@ +import os import py.test from wsgi_intercept import urllib_intercept, WSGIAppError from test import wsgi_app @@ -32,6 +33,19 @@ def test_http_other_port(): assert environ['wsgi.url_scheme'] == 'http' +def test_proxy_handling(): + """Like requests, urllib gets confused about proxy early on.""" + with py.test.raises(RuntimeError) as exc: + with InstalledApp(wsgi_app.simple_app, host=HOST, port=80, + proxy='some.host:1234'): + url_lib.urlopen('http://some_hopefully_nonexistant_domain:80/') + assert 'http_proxy or https_proxy set in environment' in str(exc.value) + # We need to do this by hand because the exception was raised + # during the entry of the context manager, so the exit handler + # wasn't reached. + del os.environ['http_proxy'] + + def test_https(): with InstalledApp(wsgi_app.simple_app, host=HOST, port=443) as app: url_lib.urlopen('https://some_hopefully_nonexistant_domain:443/') diff --git a/wsgi_intercept/__init__.py b/wsgi_intercept/__init__.py index 487cd76..b659d75 100644 --- a/wsgi_intercept/__init__.py +++ b/wsgi_intercept/__init__.py @@ -50,6 +50,11 @@ Note especially that ``app_create_fn`` is a *function object* returning a WSGI application; ``script_name`` becomes ``SCRIPT_NAME`` in the WSGI app's environment, if set. +Note also that if ``http_proxy`` or ``https_proxy`` is set in the environment +this can cause difficulties with some of the intercepted libraries. If +requests or urllib is being used, these will raise an exception if one of +those variables is set. + Install ======= diff --git a/wsgi_intercept/requests_intercept.py b/wsgi_intercept/requests_intercept.py index cdd304a..586b752 100644 --- a/wsgi_intercept/requests_intercept.py +++ b/wsgi_intercept/requests_intercept.py @@ -1,6 +1,7 @@ """Intercept HTTP connections that use `requests `_. """ +import os import sys from . import WSGI_HTTPConnection, WSGI_HTTPSConnection, wsgi_fake_socket @@ -32,6 +33,9 @@ class HTTPS_WSGIInterceptor(WSGI_HTTPSConnection, HTTPSConnection): def install(): + if 'http_proxy' in os.environ or 'https_proxy' in os.environ: + raise RuntimeError( + 'http_proxy or https_proxy set in environment, please unset') HTTPConnectionPool.ConnectionCls = HTTP_WSGIInterceptor HTTPSConnectionPool.ConnectionCls = HTTPS_WSGIInterceptor diff --git a/wsgi_intercept/urllib_intercept.py b/wsgi_intercept/urllib_intercept.py index 3eca406..31d8f46 100644 --- a/wsgi_intercept/urllib_intercept.py +++ b/wsgi_intercept/urllib_intercept.py @@ -1,5 +1,8 @@ """Intercept HTTP connections that use urllib.request (Py3) aka urllib2 (Python 2). """ + +import os + try: import urllib.request as url_lib except ImportError: @@ -27,6 +30,9 @@ class WSGI_HTTPSHandler(url_lib.HTTPSHandler): def install_opener(): + if 'http_proxy' in os.environ or 'https_proxy' in os.environ: + raise RuntimeError( + 'http_proxy or https_proxy set in environment, please unset') handlers = [WSGI_HTTPHandler()] if WSGI_HTTPSHandler is not None: handlers.append(WSGI_HTTPSHandler())