Skip to content

Commit 1d9213c

Browse files
committed
gh-86228: Initialize HTTPResponse.url in __init__ (bpo-42062)
HTTPResponse.__init__ accepted a ``url`` argument but never stored it, so geturl() raised AttributeError on responses created directly via http.client rather than through urllib. Store it on self.url and add a regression test.
1 parent 11f032f commit 1d9213c

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

Lib/http/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ def __init__(self, sock, debuglevel=0, method=None, url=None):
294294
self.length = _UNKNOWN # number of bytes left in response
295295
self.will_close = _UNKNOWN # conn will close at end of response
296296

297+
# URL of the resource, set by urllib but otherwise passed in here so
298+
# that geturl()/url work on responses created directly via http.client.
299+
self.url = url
300+
297301
def _read_status(self):
298302
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
299303
if len(line) > _MAXLINE:

Lib/test/test_httplib.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,22 @@ def test_response_headers(self):
10431043
cookies = r.getheader("Set-Cookie")
10441044
self.assertEqual(cookies, hdr)
10451045

1046+
def test_url_set_at_init(self):
1047+
# bpo-42062: HTTPResponse.url (returned by geturl()) is initialized in
1048+
# __init__, so it is available on responses created directly via
1049+
# http.client and not only on those returned by urllib. Accessing it
1050+
# previously raised AttributeError.
1051+
body = 'HTTP/1.1 200 OK\r\n\r\nText'
1052+
url = 'http://www.python.org/'
1053+
resp = client.HTTPResponse(FakeSocket(body), url=url)
1054+
self.assertEqual(resp.url, url)
1055+
self.assertEqual(resp.geturl(), url)
1056+
1057+
# When no URL is supplied, geturl() returns None instead of raising.
1058+
resp = client.HTTPResponse(FakeSocket(body))
1059+
self.assertIsNone(resp.url)
1060+
self.assertIsNone(resp.geturl())
1061+
10461062
def test_read_head(self):
10471063
# Test that the library doesn't attempt to read any data
10481064
# from a HEAD request. (Tickles SF bug #622042.)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
The :attr:`~http.client.HTTPResponse.url` attribute is now always set when an
2+
:class:`~http.client.HTTPResponse` is created. Previously it was left unset on
3+
responses created directly via :mod:`http.client`, so accessing ``url`` (or the
4+
deprecated ``geturl()``) raised :exc:`AttributeError`. Patch by Felipe
5+
Rodrigues.

0 commit comments

Comments
 (0)