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

[PR #4661/50753eac backport][3.8] Support websocket proxies configured via environment variables #6183

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/4648.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix supporting WebSockets proxies configured via environment variables.
12 changes: 9 additions & 3 deletions aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,20 @@ 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")}
proxy_urls = {
k: URL(v)
for k, v in getproxies().items()
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":
client_logger.warning("HTTPS proxies %s are not supported, ignoring", proxy)
if proxy.scheme in ("https", "wss"):
client_logger.warning(
"%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
8 changes: 6 additions & 2 deletions docs/client_advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -555,13 +555,17 @@ 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* (all are case insensitive)::

async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get("http://python.org") as resp:
print(resp.status)

.. versionadded:: 3.8

*WS_PROXY* and *WSS_PROXY* are supported since aiohttp v3.8.

Proxy credentials are given from ``~/.netrc`` file if present (see
:class:`aiohttp.ClientSession` for more details).

Expand Down
34 changes: 14 additions & 20 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,32 +462,26 @@ def test_set_content_disposition_bad_param() -> None:
# --------------------- proxies_from_env ------------------------------


def test_proxies_from_env_http(mocker) -> None:
@pytest.mark.parametrize("protocol", ["http", "https", "ws", "wss"])
def test_proxies_from_env(monkeypatch, protocol) -> None:
url = URL("http://aiohttp.io/path")
mocker.patch.dict(os.environ, {"http_proxy": str(url)})
ret = helpers.proxies_from_env()
assert ret.keys() == {"http"}
assert ret["http"].proxy == url
assert ret["http"].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)})
monkeypatch.setenv(protocol + "_proxy", str(url))
ret = helpers.proxies_from_env()
assert ret.keys() == {"https"}
assert ret["https"].proxy == url
assert ret["https"].proxy_auth is None
assert ret.keys() == {protocol}
assert ret[protocol].proxy == url
assert ret[protocol].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")
@pytest.mark.parametrize("protocol", ["https", "wss"])
def test_proxies_from_env_skipped(monkeypatch, caplog, protocol) -> None:
url = URL(protocol + "://aiohttp.io/path")
monkeypatch.setenv(protocol + "_proxy", str(url))
assert helpers.proxies_from_env() == {}
log.assert_called_with(
"HTTPS proxies %s are not supported, ignoring", URL("https://aiohttp.io/path")
assert len(caplog.records) == 1
log_message = "{proto!s} proxies {url!s} are not supported, ignoring".format(
proto=protocol.upper(), url=url
)
assert caplog.record_tuples == [("aiohttp.client", 30, log_message)]


def test_proxies_from_env_http_with_auth(mocker) -> None:
Expand Down