diff options
Diffstat (limited to 'urllib3/request.py')
-rw-r--r-- | urllib3/request.py | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/urllib3/request.py b/urllib3/request.py index c0fddff0..f1171498 100644 --- a/urllib3/request.py +++ b/urllib3/request.py @@ -1,10 +1,50 @@ from __future__ import absolute_import +import logging from .filepost import encode_multipart_formdata +from .exceptions import MaxRetryError + +from .packages.six.moves.urllib.request import Request as _Request from .packages.six.moves.urllib.parse import urlencode +from .packages.six.moves.urllib.parse import urljoin +__all__ = ['RequestMethods', 'Request'] -__all__ = ['RequestMethods'] +log = logging.getLogger(__name__) + + +class Request(_Request): + """ + Currently used as a shim to allow us to work with the stdlib cookie + handling, which expects a `urllib.request.Request`-like object. + """ + def __init__(self, *args, **kwargs): + del kwargs['method'] + # Request is an old-style class in Python 2 + _Request.__init__(self, *args, **kwargs) + self._cookies = [] + # If there's an existing Cookie header, let's split it up + # so we can handle it similarly to those we get from a jar. + if self.has_header('Cookie'): + self._cookies = self.get_header('Cookie').split('; ') + + def add_cookies(self, *cookies): + """ + We keep track of individual cookies so that we can keep them from + duplicating, and re-render the Cookie header when we get new ones. + """ + for each in cookies: + if each not in self._cookies: + self._cookies.append(each) + self.add_header('Cookie', '; '.join(self._cookies)) + + def get_all_headers(self): + """ + Returns a complete set of all headers + """ + headers = self.unredirected_hdrs.copy() + headers.update(self.headers) + return headers class RequestMethods(object): @@ -146,3 +186,24 @@ class RequestMethods(object): extra_kw.update(urlopen_kw) return self.urlopen(method, url, **extra_kw) + + def redirect(self, response, method, retries, **kwargs): + """ + Abstracts the redirect process to be used from any :class:`RequestMethods` object + """ + url = kwargs.pop('url', '') + redirect_location = urljoin(url, response.get_redirect_location()) + method = retries.redirect_method(method, response.status) + pool = kwargs.pop('pool', self) + try: + retries = retries.increment(method, url, response=response, _pool=pool) + except MaxRetryError: + if retries.raise_on_redirect: + # Release the connection for this response, since we're not + # returning it to be released manually. + response.release_conn() + raise + return response + + log.info("Redirecting %s -> %s", url, redirect_location) + return self.urlopen(method=method, url=redirect_location, retries=retries, **kwargs) |