[Python-checkins] cpython: Close #19494: add urrlib.request.HTTPBasicPriorAuthHandler
nick.coghlan
python-checkins at python.org
Wed Nov 12 14:34:16 CET 2014
https://hg.python.org/cpython/rev/fb3061ba6fd2
changeset: 93477:fb3061ba6fd2
user: Nick Coghlan <ncoghlan at gmail.com>
date: Wed Nov 12 23:33:50 2014 +1000
summary:
Close #19494: add urrlib.request.HTTPBasicPriorAuthHandler
This auth handler adds the Authorization header to the first
HTTP request rather than waiting for a HTTP 401 Unauthorized
response from the server as the default HTTPBasicAuthHandler
does.
This allows working with websites like https://api.github.com which do
not follow the strict interpretation of RFC, but more the dicta in the
end of section 2 of RFC 2617:
> A client MAY preemptively send the corresponding Authorization
> header with requests for resources in that space without receipt
> of another challenge from the server. Similarly, when a client
> sends a request to a proxy, it may reuse a userid and password in
> the Proxy-Authorization header field without receiving another
> challenge from the proxy server. See section 4 for security
> considerations associated with Basic authentication.
Patch by Matej Cepl.
files:
Doc/library/urllib.request.rst | 11 +++++++++++
Doc/whatsnew/3.5.rst | 9 +++++++++
Lib/test/test_urllib2.py | 15 +++++++++++++++
Lib/urllib/request.py | 15 +++++++++++++++
Misc/NEWS | 3 +++
5 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst
--- a/Doc/library/urllib.request.rst
+++ b/Doc/library/urllib.request.rst
@@ -304,6 +304,17 @@
presented with a wrong Authentication scheme.
+.. class:: HTTPBasicPriorAuthHandler(password_mgr=None)
+
+ A variant of :class:`HTTPBasicAuthHandler` which automatically sends
+ authorization credentials with the first request, rather than waiting to
+ first receive a HTTP 401 "Unauthorised" error response. This allows
+ authentication to sites that don't provide a 401 response when receiving
+ a request without an Authorization header. Aside from this difference,
+ this behaves exactly as :class:`HTTPBasicAuthHandler`.
+
+ .. versionadded:: 3.5
+
.. class:: ProxyBasicAuthHandler(password_mgr=None)
Handle authentication with the proxy. *password_mgr*, if given, should be
diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -297,6 +297,15 @@
* The :func:`time.monotonic` function is now always available. (Contributed by
Victor Stinner in :issue:`22043`.)
+time
+----
+
+* A new :class:`urllib.request.HTTPBasicPriorAuthHandler` allows HTTP Basic
+ Authentication credentials to be sent unconditionally with the first HTTP
+ request, rather than waiting for a HTTP 401 Unauthorized response from the
+ server.
+ (Contributed by Matej Cepl in :issue:`19494`.)
+
wsgiref
-------
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -1422,6 +1422,21 @@
handler.do_open(conn, req)
self.assertTrue(conn.fakesock.closed, "Connection not closed")
+ def test_auth_prior_handler(self):
+ pwd_manager = MockPasswordManager()
+ pwd_manager.add_password(None, 'https://example.com',
+ 'somebody', 'verysecret')
+ auth_prior_handler = urllib.request.HTTPBasicPriorAuthHandler(
+ pwd_manager)
+ http_hand = MockHTTPSHandler()
+
+ opener = OpenerDirector()
+ opener.add_handler(http_hand)
+ opener.add_handler(auth_prior_handler)
+
+ req = Request("https://example.com")
+ opener.open(req)
+ self.assertNotIn('Authorization', http_hand.httpconn.req_headers)
class MiscTests(unittest.TestCase):
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -916,6 +916,21 @@
return response
+class HTTPBasicPriorAuthHandler(HTTPBasicAuthHandler):
+ handler_order = 400
+
+ def http_request(self, req):
+ if not req.has_header('Authorization'):
+ user, passwd = self.passwd.find_user_password(None, req.host)
+ credentials = '{0}:{1}'.format(user, passwd).encode()
+ auth_str = base64.standard_b64encode(credentials).decode()
+ req.add_unredirected_header('Authorization',
+ 'Basic {}'.format(auth_str.strip()))
+ return req
+
+ https_request = http_request
+
+
# Return n random bytes.
_randombytes = os.urandom
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -183,6 +183,9 @@
Library
-------
+- Issue #19494: Added urllib.request.HTTPBasicPriorAuthHandler. Patch by
+ Matej Cepl.
+
- Issue #22578: Added attributes to the re.error class.
- Issue #12728: Different Unicode characters having the same uppercase but
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list