From 88b44b56b005f7a1cc870471d0bec95bb441f90d Mon Sep 17 00:00:00 2001 From: tboy1337 Date: Sun, 26 Oct 2025 00:49:05 +0100 Subject: [PATCH] Enhance proxy handling in SessionRedirectMixin to respect user-defined proxies during redirects. Added a flag to prevent environment proxy settings from overriding explicit user settings. Updated tests to verify correct behavior when proxies are explicitly set to None. --- src/requests/sessions.py | 16 +++++++++++----- tests/test_requests.py | 13 +++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/requests/sessions.py b/src/requests/sessions.py index 731550de88..e58ac9024e 100644 --- a/src/requests/sessions.py +++ b/src/requests/sessions.py @@ -166,6 +166,7 @@ def resolve_redirects( cert=None, proxies=None, yield_requests=False, + _user_explicitly_set_proxies=False, **adapter_kwargs, ): """Receives a Response. Returns a generator of Responses or Requests.""" @@ -242,7 +243,7 @@ def resolve_redirects( prepared_request.prepare_cookies(prepared_request._cookies) # Rebuild auth and proxy information. - proxies = self.rebuild_proxies(prepared_request, proxies) + proxies = self.rebuild_proxies(prepared_request, proxies, _user_explicitly_set_proxies) self.rebuild_auth(prepared_request, resp) # A failed tell() sets `_body_position` to `object()`. This non-None @@ -299,7 +300,7 @@ def rebuild_auth(self, prepared_request, response): if new_auth is not None: prepared_request.prepare_auth(new_auth) - def rebuild_proxies(self, prepared_request, proxies): + def rebuild_proxies(self, prepared_request, proxies, _user_explicitly_set_proxies=False): """This method re-evaluates the proxy configuration by considering the environment variables. If we are redirected to a URL covered by NO_PROXY, we strip the proxy configuration. Otherwise, we set missing @@ -313,7 +314,9 @@ def rebuild_proxies(self, prepared_request, proxies): """ headers = prepared_request.headers scheme = urlparse(prepared_request.url).scheme - new_proxies = resolve_proxies(prepared_request, proxies, self.trust_env) + # Don't trust environment if user explicitly set proxies (even if empty after merge) + trust_env = self.trust_env if not _user_explicitly_set_proxies else False + new_proxies = resolve_proxies(prepared_request, proxies, trust_env) if "Proxy-Authorization" in headers: del headers["Proxy-Authorization"] @@ -720,7 +723,9 @@ def send(self, request, **kwargs): # Resolve redirects if allowed. if allow_redirects: # Redirect resolving generator. - gen = self.resolve_redirects(r, request, **kwargs) + # Track if user explicitly set proxies to avoid environment override on redirects + user_set_proxies = "proxies" in kwargs and kwargs.get("proxies") is not None + gen = self.resolve_redirects(r, request, _user_explicitly_set_proxies=user_set_proxies, **kwargs) history = [resp for resp in gen] else: history = [] @@ -736,8 +741,9 @@ def send(self, request, **kwargs): # If redirects aren't being followed, store the response on the Request for Response.next(). if not allow_redirects: try: + user_set_proxies = "proxies" in kwargs and kwargs.get("proxies") is not None r._next = next( - self.resolve_redirects(r, request, yield_requests=True, **kwargs) + self.resolve_redirects(r, request, yield_requests=True, _user_explicitly_set_proxies=user_set_proxies, **kwargs) ) except StopIteration: pass diff --git a/tests/test_requests.py b/tests/test_requests.py index 75d2deff2e..a67961934e 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -670,6 +670,19 @@ def test_proxy_authorization_not_appended_to_https_request( assert ("Proxy-Authorization" in prep.headers) is has_proxy_auth + def test_proxy_bypass_on_redirect_with_explicit_none(self, httpbin): + """Test that explicit proxies={'http': None} bypasses proxy on redirects. + + This tests issue #6981 where redirects would incorrectly use environment + proxy settings even when the user explicitly passed proxies={'http': None} + to bypass the proxy. + """ + with override_environ(http_proxy=INVALID_PROXY): + # This should succeed because we explicitly bypass the proxy + session = requests.Session() + resp = session.get(httpbin("redirect/1"), proxies={'http': None, 'https': None}) + assert resp.status_code == 200 + def test_basicauth_with_netrc(self, httpbin): auth = ("user", "pass") wrong_auth = ("wronguser", "wrongpass")