From d437c338d0bfe4a88d9c3efa1a1802603ee9cc97 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Wed, 6 Feb 2013 18:24:23 +0000 Subject: [PATCH] Add Proxy-Auth header when proxies have credentials. --- requests/adapters.py | 19 ++++++++++++++++++- requests/utils.py | 10 ++++++++++ test_requests.py | 5 +++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/requests/adapters.py b/requests/adapters.py index c350ae4..4b58f45 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -15,7 +15,7 @@ from .packages.urllib3.poolmanager import PoolManager, ProxyManager from .packages.urllib3.response import HTTPResponse from .compat import urlparse, basestring, urldefrag from .utils import (DEFAULT_CA_BUNDLE_PATH, get_encoding_from_headers, - prepend_scheme_if_needed) + prepend_scheme_if_needed, get_auth_from_url) from .structures import CaseInsensitiveDict from .packages.urllib3.exceptions import MaxRetryError from .packages.urllib3.exceptions import TimeoutError @@ -23,6 +23,7 @@ from .packages.urllib3.exceptions import SSLError as _SSLError from .packages.urllib3.exceptions import HTTPError as _HTTPError from .cookies import extract_cookies_to_jar from .exceptions import ConnectionError, Timeout, SSLError +from .auth import _basic_auth_str DEFAULT_POOLSIZE = 10 DEFAULT_RETRIES = 0 @@ -146,6 +147,21 @@ class HTTPAdapter(BaseAdapter): return url + def add_headers(self, request, **kwargs): + """Add any headers needed by the connection. Currently this only adds a + Host: header if a proxy is being used.""" + proxies = kwargs.get('proxies', {}) + + if proxies is None: + proxies = {} + + proxy = proxies.get(urlparse(request.url).scheme) + username, password = get_auth_from_url(proxy) + + if username and password: + request.headers['Proxy-Authorization'] = _basic_auth_str(username, + password) + def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): """Sends PreparedRequest object. Returns Response object.""" @@ -153,6 +169,7 @@ class HTTPAdapter(BaseAdapter): self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) + self.add_headers(request, proxies=proxies) chunked = not (request.body is None or 'Content-Length' in request.headers) diff --git a/requests/utils.py b/requests/utils.py index 91bb3e8..bb07f83 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -580,3 +580,13 @@ def prepend_scheme_if_needed(url, new_scheme): netloc, path = path, netloc return urlunparse((scheme, netloc, path, params, query, fragment)) + + +def get_auth_from_url(url): + """Given a url with authentication components, extract them into a tuple of + username,password.""" + if url: + parsed = urlparse(url) + return (parsed.username, parsed.password) + else: + return ('', '') diff --git a/test_requests.py b/test_requests.py index 72c6eb7..4ba9a43 100644 --- a/test_requests.py +++ b/test_requests.py @@ -336,5 +336,10 @@ class RequestsTestCase(unittest.TestCase): self.assertTrue(next(iter(r))) io.close() + def test_get_auth_from_url(self): + url = 'http://user:pass@complex.url.com/path?query=yes' + self.assertEqual(('user', 'pass'), + requests.utils.get_auth_from_url(url)) + if __name__ == '__main__': unittest.main() -- 2.7.4