Redirect cache
diff --git a/requests/models.py b/requests/models.py
index b43901b7db..0dc5556838 100644
--- a/requests/models.py
+++ b/requests/models.py
@@ -610,6 +610,11 @@ def is_redirect(self):
         """
         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"""
diff --git a/requests/sessions.py b/requests/sessions.py
index 5827d9176b..a263138aad 100644
--- a/requests/sessions.py
+++ b/requests/sessions.py
@@ -127,6 +127,9 @@ def resolve_redirects(self, resp, req, stream=False, timeout=None,
                 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 @@ def __init__(self):
         self.mount('https://', HTTPAdapter())
         self.mount('http://', HTTPAdapter())
 
+        self.redirect_cache = {}
+
     def __enter__(self):
         return self
 
@@ -540,6 +545,9 @@ def send(self, request, **kwargs):
         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')

When web clients like Firefox get a redirect they will not go after the old version any more even if you type it into the address bar.
This patch makes the requests framework work in the same way.
This helps performance when creating a request proxy that delegates to other servers based on URL.
This patch has me going from 245 requests per second to 470 requests per second against a server returning 308 response codes.

-- example server
https://gist.github.com/ericfrederich/a004862e1da1fb6916ef
-- example client
https://gist.github.com/ericfrederich/e1225e2d07e3ee923b27
-- example server output of 301 vs 302 redireects
https://gist.github.com/ericfrederich/b77bd4852a3cf9b968f0
