diff --git a/requests/sessions.py b/requests/sessions.py index ae4bcc8e79..3f59cab922 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -29,7 +29,7 @@ from .utils import ( requote_uri, get_environ_proxies, get_netrc_auth, should_bypass_proxies, - get_auth_from_url, rewind_body + get_auth_from_url, rewind_body, resolve_proxies ) from .status_codes import codes @@ -269,7 +269,6 @@ 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): """This method re-evaluates the proxy configuration by considering the environment variables. If we are redirected to a URL covered by @@ -282,21 +281,9 @@ def rebuild_proxies(self, prepared_request, proxies): :rtype: dict """ - proxies = proxies if proxies is not None else {} headers = prepared_request.headers - url = prepared_request.url - scheme = urlparse(url).scheme - new_proxies = proxies.copy() - no_proxy = proxies.get('no_proxy') - - bypass_proxy = should_bypass_proxies(url, no_proxy=no_proxy) - if self.trust_env and not bypass_proxy: - environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) - - proxy = environ_proxies.get(scheme, environ_proxies.get('all')) - - if proxy: - new_proxies.setdefault(scheme, proxy) + scheme = urlparse(prepared_request.url).scheme + new_proxies = resolve_proxies(prepared_request, proxies, self.trust_env) if 'Proxy-Authorization' in headers: del headers['Proxy-Authorization'] @@ -633,7 +620,10 @@ def send(self, request, **kwargs): kwargs.setdefault('stream', self.stream) kwargs.setdefault('verify', self.verify) kwargs.setdefault('cert', self.cert) - kwargs.setdefault('proxies', self.rebuild_proxies(request, self.proxies)) + if 'proxies' not in kwargs: + kwargs['proxies'] = resolve_proxies( + request, self.proxies, self.trust_env + ) # It's possible that users might accidentally send a Request object. # Guard against that specific failure case. diff --git a/requests/utils.py b/requests/utils.py index 41bfb82fe0..53c282dadc 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -830,6 +830,34 @@ def select_proxy(url, proxies): return proxy +def resolve_proxies(request, proxies, trust_env=True): + """This method takes proxy information from a request and configuration + input to resolve a mapping of target proxies. This will consider settings + such a NO_PROXY to strip proxy configurations. + + :param request: Request or PreparedRequest + :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs + :param trust_env: Boolean declaring whether to trust environment configs + + :rtype: dict + """ + proxies = proxies if proxies is not None else {} + url = request.url + scheme = urlparse(url).scheme + no_proxy = proxies.get('no_proxy') + new_proxies = proxies.copy() + + bypass_proxy = should_bypass_proxies(url, no_proxy=no_proxy) + if trust_env and not bypass_proxy: + environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) + + proxy = environ_proxies.get(scheme, environ_proxies.get('all')) + + if proxy: + new_proxies.setdefault(scheme, proxy) + return new_proxies + + def default_user_agent(name="python-requests"): """ Return a string representing the default user agent. diff --git a/tests/test_requests.py b/tests/test_requests.py index b6d97dd9f4..463e8bf47a 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -590,6 +590,15 @@ def test_respect_proxy_env_on_request(self, httpbin): session = requests.Session() session.request(method='GET', url=httpbin()) + def test_proxy_authorization_preserved_on_request(self, httpbin): + proxy_auth_value = "Bearer XXX" + session = requests.Session() + session.headers.update({"Proxy-Authorization": proxy_auth_value}) + resp = session.request(method='GET', url=httpbin('get')) + sent_headers = resp.json().get('headers', {}) + + assert sent_headers.get("Proxy-Authorization") == proxy_auth_value + def test_basicauth_with_netrc(self, httpbin): auth = ('user', 'pass') wrong_auth = ('wronguser', 'wrongpass') @@ -2575,4 +2584,4 @@ def test_post_json_nan(self, httpbin): def test_json_decode_compatibility(self, httpbin): r = requests.get(httpbin('bytes/20')) with pytest.raises(requests.exceptions.JSONDecodeError): - r.json() \ No newline at end of file + r.json()