don't make duplicate requests for permanent redirects
authorEric L Frederich <eric.frederich@siemens.com>
Thu, 12 Jun 2014 12:25:21 +0000 (08:25 -0400)
committerEric L Frederich <eric.frederich@siemens.com>
Thu, 12 Jun 2014 12:25:21 +0000 (08:25 -0400)
requests/models.py
requests/sessions.py

index b43901b7dbd7ab0027be7463823d37e0c94fbd35..0dc5556838c734e0a24d4795dcf16cd6003871c5 100644 (file)
@@ -610,6 +610,11 @@ class Response(object):
         """
         return ('location' in self.headers and self.status_code in REDIRECT_STATI)
 
+    @property
+    def is_permanent_redirect(self):
+        """True if this Response one of the permanant versions of redirect"""
+        return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect))
+
     @property
     def apparent_encoding(self):
         """The apparent encoding, provided by the chardet library"""
index 5827d9176bcfc978e1e002ef34934b21ef95279a..a263138aadc67d29a86e50e7ec5655ff74795b62 100644 (file)
@@ -127,6 +127,9 @@ class SessionRedirectMixin(object):
                 url = requote_uri(url)
 
             prepared_request.url = to_native_string(url)
+            # cache the url
+            if resp.is_permanent_redirect:
+                self.redirect_cache[req.url] = prepared_request.url
 
             # http://tools.ietf.org/html/rfc7231#section-6.4.4
             if (resp.status_code == codes.see_other and
@@ -263,7 +266,7 @@ class Session(SessionRedirectMixin):
     __attrs__ = [
         'headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks',
         'params', 'verify', 'cert', 'prefetch', 'adapters', 'stream',
-        'trust_env', 'max_redirects']
+        'trust_env', 'max_redirects', 'redirect_cache']
 
     def __init__(self):
 
@@ -316,6 +319,8 @@ class Session(SessionRedirectMixin):
         self.mount('https://', HTTPAdapter())
         self.mount('http://', HTTPAdapter())
 
+        self.redirect_cache = {}
+
     def __enter__(self):
         return self
 
@@ -540,6 +545,9 @@ class Session(SessionRedirectMixin):
         if not isinstance(request, PreparedRequest):
             raise ValueError('You can only send PreparedRequests.')
 
+        while request.url in self.redirect_cache:
+            request.url = self.redirect_cache.get(request.url)
+
         # Set up variables needed for resolve_redirects and dispatching of hooks
         allow_redirects = kwargs.pop('allow_redirects', True)
         stream = kwargs.get('stream')