Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ Changes in Apache Libcloud 3.9.2
Common
~~~~~~

- Respect the ``no_proxy`` / ``NO_PROXY`` environment variable so an explicitly
configured proxy is bypassed for matching hosts.
(GITHUB-2077)
[Sanjay Santhanam - @Sanjays2402]

- Move tests to python 3.12.
(#2152)
[Miguel Caballer - @micafer]
Expand Down
24 changes: 24 additions & 0 deletions libcloud/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import requests
from requests.adapters import HTTPAdapter
from requests.utils import should_bypass_proxies

import libcloud.security
from libcloud.utils.py3 import urlparse
Expand Down Expand Up @@ -112,6 +113,28 @@ def set_http_proxy(self, proxy_url):
"https": proxy_url,
}


def _proxies_for_url(self, url):
"""
Return the proxy mapping to use for ``url``.

An explicitly configured proxy is skipped when the target host matches
the ``no_proxy`` / ``NO_PROXY`` environment variable, so libcloud
behaves consistently with other HTTP clients.

:param url: Absolute request URL.
:type url: ``str``

:rtype: ``dict`` or ``None``
"""
if not self.session.proxies:
return None

if should_bypass_proxies(url, no_proxy=None):
return {}

return None

def _parse_proxy_url(self, proxy_url):
"""
Parse and validate a proxy URL.
Expand Down Expand Up @@ -231,6 +254,7 @@ def request(self, method, url, body=None, headers=None, raw=False, stream=False,
verify=self.verification,
timeout=self.session.timeout,
hooks=hooks,
proxies=self._proxies_for_url(url),
)

def prepared_request(self, method, url, body=None, headers=None, raw=False, stream=False):
Expand Down
12 changes: 12 additions & 0 deletions libcloud/test/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ def test_constructor(self):
{"http": "https://127.0.0.6:3129", "https": "https://127.0.0.6:3129"},
)

def test_proxy_is_bypassed_for_no_proxy_hosts(self):
# Regression test for GITHUB-2077: an explicitly configured proxy must
# not be used for hosts listed in the no_proxy environment variable.
os.environ["no_proxy"] = "internal.example.com"
self.addCleanup(os.environ.pop, "no_proxy", None)

conn = LibcloudConnection(host="internal.example.com", port=443)
conn.set_http_proxy("http://proxy.example.com:3128")

self.assertEqual(conn._proxies_for_url("https://internal.example.com/path"), {})
self.assertIsNone(conn._proxies_for_url("https://other.example.com/path"))

def test_proxy_environment_variables_respected(self):
"""
Test that proxy environment variables are respected by the underlying Requests library
Expand Down