summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth M. Larson <SethMichaelLarson@users.noreply.github.com>2018-04-30 12:08:04 -0500
committerGitHub <noreply@github.com>2018-04-30 12:08:04 -0500
commit5243c46939e664494e640b8e459d6dad726287ad (patch)
treeb847a31ae96bb17a293f75b4e43701e0fb381e3f
parentdb444ec77836ef1e6aa129bc3507f8e838f1ceb6 (diff)
parentfc210c543bfb62ae3f1bbbc5d873fa39bd048ff4 (diff)
downloadurllib3-5243c46939e664494e640b8e459d6dad726287ad.tar.gz
Add geturl method to HTTPResponse objects (#1382)
Implements #1272 by adding a geturl method to HTTPResponse objects
-rw-r--r--CONTRIBUTORS.txt4
-rw-r--r--test/test_response.py20
-rw-r--r--urllib3/request.py2
-rw-r--r--urllib3/response.py15
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