Skip to content

Commit 5c00a62

Browse files
wheelerlawgpsheadorsenthil
authored
gh-99352: Respect http.client.HTTPConnection.debuglevel in urllib.request.AbstractHTTPHandler (#99353)
* bugfix: let the HTTP- and HTTPSHandlers respect the value of http.client.HTTPConnection.debuglevel * add tests * add news * ReSTify NEWS and reword a bit. * Address Review Comments. * Use mock.patch.object instead of settting the module level value. * Used test values to assert the debuglevel. --------- Co-authored-by: Gregory P. Smith <[email protected]> Co-authored-by: Senthil Kumaran <[email protected]>
1 parent 4898415 commit 5c00a62

File tree

3 files changed

+57
-18
lines changed

3 files changed

+57
-18
lines changed

Lib/test/test_urllib2.py

+50-15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from test.support import os_helper
44
from test.support import warnings_helper
55
from test import test_urllib
6+
from unittest import mock
67

78
import os
89
import io
@@ -484,7 +485,18 @@ def build_test_opener(*handler_instances):
484485
return opener
485486

486487

487-
class MockHTTPHandler(urllib.request.BaseHandler):
488+
class MockHTTPHandler(urllib.request.HTTPHandler):
489+
# Very simple mock HTTP handler with no special behavior other than using a mock HTTP connection
490+
491+
def __init__(self, debuglevel=None):
492+
super(MockHTTPHandler, self).__init__(debuglevel=debuglevel)
493+
self.httpconn = MockHTTPClass()
494+
495+
def http_open(self, req):
496+
return self.do_open(self.httpconn, req)
497+
498+
499+
class MockHTTPHandlerRedirect(urllib.request.BaseHandler):
488500
# useful for testing redirections and auth
489501
# sends supplied headers and code as first response
490502
# sends 200 OK as second response
@@ -512,12 +524,12 @@ def http_open(self, req):
512524
return MockResponse(200, "OK", msg, "", req.get_full_url())
513525

514526

515-
class MockHTTPSHandler(urllib.request.AbstractHTTPHandler):
527+
class MockHTTPSHandler(urllib.request.HTTPSHandler):
516528
# Useful for testing the Proxy-Authorization request by verifying the
517529
# properties of httpcon
518530

519-
def __init__(self, debuglevel=0):
520-
urllib.request.AbstractHTTPHandler.__init__(self, debuglevel=debuglevel)
531+
def __init__(self, debuglevel=None, context=None, check_hostname=None):
532+
super(MockHTTPSHandler, self).__init__(debuglevel, context, check_hostname)
521533
self.httpconn = MockHTTPClass()
522534

523535
def https_open(self, req):
@@ -1048,12 +1060,35 @@ def test_http_body_array(self):
10481060
newreq = h.do_request_(req)
10491061
self.assertEqual(int(newreq.get_header('Content-length')),16)
10501062

1051-
def test_http_handler_debuglevel(self):
1063+
def test_http_handler_global_debuglevel(self):
1064+
with mock.patch.object(http.client.HTTPConnection, 'debuglevel', 6):
1065+
o = OpenerDirector()
1066+
h = MockHTTPHandler()
1067+
o.add_handler(h)
1068+
o.open("http://www.example.com")
1069+
self.assertEqual(h._debuglevel, 6)
1070+
1071+
def test_http_handler_local_debuglevel(self):
1072+
o = OpenerDirector()
1073+
h = MockHTTPHandler(debuglevel=5)
1074+
o.add_handler(h)
1075+
o.open("http://www.example.com")
1076+
self.assertEqual(h._debuglevel, 5)
1077+
1078+
def test_https_handler_global_debuglevel(self):
1079+
with mock.patch.object(http.client.HTTPSConnection, 'debuglevel', 7):
1080+
o = OpenerDirector()
1081+
h = MockHTTPSHandler()
1082+
o.add_handler(h)
1083+
o.open("https://www.example.com")
1084+
self.assertEqual(h._debuglevel, 7)
1085+
1086+
def test_https_handler_local_debuglevel(self):
10521087
o = OpenerDirector()
1053-
h = MockHTTPSHandler(debuglevel=1)
1088+
h = MockHTTPSHandler(debuglevel=4)
10541089
o.add_handler(h)
10551090
o.open("https://www.example.com")
1056-
self.assertEqual(h._debuglevel, 1)
1091+
self.assertEqual(h._debuglevel, 4)
10571092

10581093
def test_http_doubleslash(self):
10591094
# Checks the presence of any unnecessary double slash in url does not
@@ -1289,7 +1324,7 @@ def test_cookie_redirect(self):
12891324

12901325
cj = CookieJar()
12911326
interact_netscape(cj, "http://www.example.com/", "spam=eggs")
1292-
hh = MockHTTPHandler(302, "Location: http://www.cracker.com/\r\n\r\n")
1327+
hh = MockHTTPHandlerRedirect(302, "Location: http://www.cracker.com/\r\n\r\n")
12931328
hdeh = urllib.request.HTTPDefaultErrorHandler()
12941329
hrh = urllib.request.HTTPRedirectHandler()
12951330
cp = urllib.request.HTTPCookieProcessor(cj)
@@ -1299,7 +1334,7 @@ def test_cookie_redirect(self):
12991334

13001335
def test_redirect_fragment(self):
13011336
redirected_url = 'http://www.example.com/index.html#OK\r\n\r\n'
1302-
hh = MockHTTPHandler(302, 'Location: ' + redirected_url)
1337+
hh = MockHTTPHandlerRedirect(302, 'Location: ' + redirected_url)
13031338
hdeh = urllib.request.HTTPDefaultErrorHandler()
13041339
hrh = urllib.request.HTTPRedirectHandler()
13051340
o = build_test_opener(hh, hdeh, hrh)
@@ -1484,7 +1519,7 @@ def check_basic_auth(self, headers, realm):
14841519
password_manager = MockPasswordManager()
14851520
auth_handler = urllib.request.HTTPBasicAuthHandler(password_manager)
14861521
body = '\r\n'.join(headers) + '\r\n\r\n'
1487-
http_handler = MockHTTPHandler(401, body)
1522+
http_handler = MockHTTPHandlerRedirect(401, body)
14881523
opener.add_handler(auth_handler)
14891524
opener.add_handler(http_handler)
14901525
self._test_basic_auth(opener, auth_handler, "Authorization",
@@ -1544,7 +1579,7 @@ def test_proxy_basic_auth(self):
15441579
password_manager = MockPasswordManager()
15451580
auth_handler = urllib.request.ProxyBasicAuthHandler(password_manager)
15461581
realm = "ACME Networks"
1547-
http_handler = MockHTTPHandler(
1582+
http_handler = MockHTTPHandlerRedirect(
15481583
407, 'Proxy-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
15491584
opener.add_handler(auth_handler)
15501585
opener.add_handler(http_handler)
@@ -1588,7 +1623,7 @@ def http_error_401(self, *args, **kwds):
15881623
digest_handler = TestDigestAuthHandler(password_manager)
15891624
basic_handler = TestBasicAuthHandler(password_manager)
15901625
realm = "ACME Networks"
1591-
http_handler = MockHTTPHandler(
1626+
http_handler = MockHTTPHandlerRedirect(
15921627
401, 'WWW-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
15931628
opener.add_handler(basic_handler)
15941629
opener.add_handler(digest_handler)
@@ -1608,7 +1643,7 @@ def test_unsupported_auth_digest_handler(self):
16081643
opener = OpenerDirector()
16091644
# While using DigestAuthHandler
16101645
digest_auth_handler = urllib.request.HTTPDigestAuthHandler(None)
1611-
http_handler = MockHTTPHandler(
1646+
http_handler = MockHTTPHandlerRedirect(
16121647
401, 'WWW-Authenticate: Kerberos\r\n\r\n')
16131648
opener.add_handler(digest_auth_handler)
16141649
opener.add_handler(http_handler)
@@ -1618,7 +1653,7 @@ def test_unsupported_auth_basic_handler(self):
16181653
# While using BasicAuthHandler
16191654
opener = OpenerDirector()
16201655
basic_auth_handler = urllib.request.HTTPBasicAuthHandler(None)
1621-
http_handler = MockHTTPHandler(
1656+
http_handler = MockHTTPHandlerRedirect(
16221657
401, 'WWW-Authenticate: NTLM\r\n\r\n')
16231658
opener.add_handler(basic_auth_handler)
16241659
opener.add_handler(http_handler)
@@ -1705,7 +1740,7 @@ def test_basic_prior_auth_send_after_first_success(self):
17051740
opener = OpenerDirector()
17061741
opener.add_handler(auth_prior_handler)
17071742

1708-
http_handler = MockHTTPHandler(
1743+
http_handler = MockHTTPHandlerRedirect(
17091744
401, 'WWW-Authenticate: Basic realm="%s"\r\n\r\n' % None)
17101745
opener.add_handler(http_handler)
17111746

Lib/urllib/request.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1251,8 +1251,8 @@ def http_error_407(self, req, fp, code, msg, headers):
12511251

12521252
class AbstractHTTPHandler(BaseHandler):
12531253

1254-
def __init__(self, debuglevel=0):
1255-
self._debuglevel = debuglevel
1254+
def __init__(self, debuglevel=None):
1255+
self._debuglevel = debuglevel if debuglevel is not None else http.client.HTTPConnection.debuglevel
12561256

12571257
def set_http_debuglevel(self, level):
12581258
self._debuglevel = level
@@ -1378,7 +1378,8 @@ def http_open(self, req):
13781378

13791379
class HTTPSHandler(AbstractHTTPHandler):
13801380

1381-
def __init__(self, debuglevel=0, context=None, check_hostname=None):
1381+
def __init__(self, debuglevel=None, context=None, check_hostname=None):
1382+
debuglevel = debuglevel if debuglevel is not None else http.client.HTTPSConnection.debuglevel
13821383
AbstractHTTPHandler.__init__(self, debuglevel)
13831384
if context is None:
13841385
http_version = http.client.HTTPSConnection._http_vsn
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Respect the :class:`http.client.HTTPConnection` ``.debuglevel`` flag
2+
in :class:`urllib.request.AbstractHTTPHandler` when its constructor
3+
parameter ``debuglevel`` is not set. And do the same for ``*HTTPS*``.

0 commit comments

Comments
 (0)