Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support websocket proxies configured via environment variables #4661

Merged
merged 9 commits into from Mar 26, 2020
Merged
1 change: 1 addition & 0 deletions CHANGES/4648.bugfix
@@ -0,0 +1 @@
Fix issue with proxy configured by environment variables for websockets.
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Expand Up @@ -175,6 +175,7 @@ Manuel Miranda
Marat Sharafutdinov
Marco Paolini
Mariano Anaya
Mariusz Masztalerczuk
Martijn Pieters
Martin Melka
Martin Richard
Expand Down
7 changes: 4 additions & 3 deletions aiohttp/helpers.py
Expand Up @@ -229,15 +229,16 @@ class ProxyInfo:

def proxies_from_env() -> Dict[str, ProxyInfo]:
proxy_urls = {k: URL(v) for k, v in getproxies().items()
if k in ('http', 'https')}
if k in ('http', 'https', 'ws', 'wss')}
netrc_obj = netrc_from_env()
stripped = {k: strip_auth_from_url(v) for k, v in proxy_urls.items()}
ret = {}
for proto, val in stripped.items():
proxy, auth = val
if proxy.scheme == 'https':
if proxy.scheme in ('https', 'ws', 'wss'):
mmasztalerczuk marked this conversation as resolved.
Show resolved Hide resolved
client_logger.warning(
"HTTPS proxies %s are not supported, ignoring", proxy)
"%s proxies %s are not supported, ignoring",
proxy.scheme.upper(), proxy)
continue
if netrc_obj and auth is None:
auth_from_netrc = None
Expand Down
4 changes: 2 additions & 2 deletions docs/client_advanced.rst
Expand Up @@ -527,8 +527,8 @@ Contrary to the ``requests`` library, it won't read environment
variables by default. But you can do so by passing
``trust_env=True`` into :class:`aiohttp.ClientSession`
constructor for extracting proxy configuration from
*HTTP_PROXY* or *HTTPS_PROXY* *environment variables* (both are case
insensitive)::
*HTTP_PROXY*, *HTTPS_PROXY*, *WS_PROXY* or *WSS_PROXY* *environment
variables* (both are case insensitive)::
webknjaz marked this conversation as resolved.
Show resolved Hide resolved

async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get("http://python.org") as resp:
Expand Down
37 changes: 35 additions & 2 deletions tests/test_helpers.py
Expand Up @@ -423,6 +423,15 @@ def test_proxies_from_env_http(mocker) -> None:
assert ret['http'].proxy_auth is None


def test_proxies_from_env_http_proxy_for_ws_proto(mocker) -> None:
url = URL('http://aiohttp.io/path')
mocker.patch.dict(os.environ, {'ws_proxy': str(url)})
ret = helpers.proxies_from_env()
assert ret.keys() == {'ws'}
assert ret['ws'].proxy == url
assert ret['ws'].proxy_auth is None


def test_proxies_from_env_http_proxy_for_https_proto(mocker) -> None:
url = URL('http://aiohttp.io/path')
mocker.patch.dict(os.environ, {'https_proxy': str(url)})
Expand All @@ -431,14 +440,38 @@ def test_proxies_from_env_http_proxy_for_https_proto(mocker) -> None:
assert ret['https'].proxy == url
assert ret['https'].proxy_auth is None

def test_proxies_from_env_http_proxy_for_wss_proto(mocker) -> None:
url = URL('http://aiohttp.io/path')
mocker.patch.dict(os.environ, {'wss_proxy': str(url)})
mmasztalerczuk marked this conversation as resolved.
Show resolved Hide resolved
ret = helpers.proxies_from_env()
assert ret.keys() == {'wss'}
assert ret['wss'].proxy == url
assert ret['wss'].proxy_auth is None


def test_proxies_from_env_https_proxy_skipped(mocker) -> None:
url = URL('https://aiohttp.io/path')
mocker.patch.dict(os.environ, {'https_proxy': str(url)})
log = mocker.patch('aiohttp.log.client_logger.warning')
assert helpers.proxies_from_env() == {}
log.assert_called_with('HTTPS proxies %s are not supported, ignoring',
URL('https://aiohttp.io/path'))
log.assert_called_with('%s proxies %s are not supported, ignoring',
'HTTPS', URL('https://aiohttp.io/path'))

def test_proxies_from_env_ws_proxy_skipped(mocker) -> None:
mmasztalerczuk marked this conversation as resolved.
Show resolved Hide resolved
url = URL('ws://aiohttp.io/path')
mocker.patch.dict(os.environ, {'wss_proxy': str(url)})
log = mocker.patch('aiohttp.log.client_logger.warning')
mmasztalerczuk marked this conversation as resolved.
Show resolved Hide resolved
assert helpers.proxies_from_env() == {}
log.assert_called_with('%s proxies %s are not supported, ignoring',
'WS', URL('ws://aiohttp.io/path'))

def test_proxies_from_env_wss_proxy_skipped(mocker) -> None:
url = URL('wss://aiohttp.io/path')
mocker.patch.dict(os.environ, {'wss_proxy': str(url)})
log = mocker.patch('aiohttp.log.client_logger.warning')
assert helpers.proxies_from_env() == {}
log.assert_called_with('%s proxies %s are not supported, ignoring',
'WSS', URL('wss://aiohttp.io/path'))


def test_proxies_from_env_http_with_auth(mocker) -> None:
Expand Down