diff options
author | Seth M. Larson <SethMichaelLarson@users.noreply.github.com> | 2018-04-30 12:08:04 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-30 12:08:04 -0500 |
commit | 5243c46939e664494e640b8e459d6dad726287ad (patch) | |
tree | b847a31ae96bb17a293f75b4e43701e0fb381e3f | |
parent | db444ec77836ef1e6aa129bc3507f8e838f1ceb6 (diff) | |
parent | fc210c543bfb62ae3f1bbbc5d873fa39bd048ff4 (diff) | |
download | urllib3-5243c46939e664494e640b8e459d6dad726287ad.tar.gz |
Add geturl method to HTTPResponse objects (#1382)
Implements #1272 by adding a geturl method to HTTPResponse objects
-rw-r--r-- | CONTRIBUTORS.txt | 4 | ||||
-rw-r--r-- | test/test_response.py | 20 | ||||
-rw-r--r-- | urllib3/request.py | 2 | ||||
-rw-r--r-- | urllib3/response.py | 15 |
4 files changed, 39 insertions, 2 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 03682a66..453277eb 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -255,5 +255,9 @@ In chronological order: * Aleksei Alekseev <alekseev.yeskela@gmail.com> * using auth info for socks proxy +* Chris Wilcox <git@crwilcox.com> + * Improve contribution guide + * Add ``HTTPResponse.geturl`` method to provide ``urllib2.urlopen().geturl()`` behavior + * [Your name or handle] <[email or website]> * [Brief summary of your changes] diff --git a/test/test_response.py b/test/test_response.py index 86ac786b..0b347c25 100644 --- a/test/test_response.py +++ b/test/test_response.py @@ -11,7 +11,7 @@ from urllib3.exceptions import ( DecodeError, ResponseNotChunked, ProtocolError, InvalidHeader ) from urllib3.packages.six.moves import http_client as httplib -from urllib3.util.retry import Retry +from urllib3.util.retry import Retry, RequestHistory from urllib3.util.response import is_fp_closed from base64 import b64decode @@ -675,6 +675,24 @@ class TestResponse(object): resp = HTTPResponse(fp, retries=retry) assert resp.retries == retry + def test_geturl(self): + fp = BytesIO(b'') + request_url = 'https://example.com' + resp = HTTPResponse(fp, request_url=request_url) + assert resp.geturl() == request_url + + def test_geturl_retries(self): + fp = BytesIO(b'') + resp = HTTPResponse(fp, request_url='http://example.com') + request_histories = [ + RequestHistory(method='GET', url='http://example.com', error=None, + status=301, redirect_location='https://example.com/'), + RequestHistory(method='GET', url='https://example.com/', error=None, + status=301, redirect_location='https://www.example.com')] + retry = Retry(history=request_histories) + resp = HTTPResponse(fp, retries=retry) + assert resp.geturl() == 'https://www.example.com' + class MockChunkedEncodingResponse(object): diff --git a/urllib3/request.py b/urllib3/request.py index 855f25a3..1be33341 100644 --- a/urllib3/request.py +++ b/urllib3/request.py @@ -60,6 +60,8 @@ class RequestMethods(object): """ method = method.upper() + urlopen_kw['request_url'] = url + if method in self._encode_url_methods: return self.request_encode_url(method, url, fields=fields, headers=headers, diff --git a/urllib3/response.py b/urllib3/response.py index 20d55a8d..dee3f3c2 100644 --- a/urllib3/response.py +++ b/urllib3/response.py @@ -136,7 +136,8 @@ class HTTPResponse(io.IOBase): def __init__(self, body='', headers=None, status=0, version=0, reason=None, strict=0, preload_content=True, decode_content=True, original_response=None, pool=None, connection=None, msg=None, - retries=None, enforce_content_length=False, request_method=None): + retries=None, enforce_content_length=False, + request_method=None, request_url=None): if isinstance(headers, HTTPHeaderDict): self.headers = headers @@ -156,6 +157,7 @@ class HTTPResponse(io.IOBase): self._original_response = original_response self._fp_bytes_read = 0 self.msg = msg + self._request_url = request_url if body and isinstance(body, (basestring, binary_type)): self._body = body @@ -661,3 +663,14 @@ class HTTPResponse(io.IOBase): # We read everything; close the "file". if self._original_response: self._original_response.close() + + def geturl(self): + """ + Returns the URL that was the source of this response. + If the request that generated this response redirected, this method + will return the final redirect location. + """ + if self.retries is not None and len(self.retries.history): + return self.retries.history[-1].redirect_location + else: + return self._request_url |