diff --git a/requests/models.py b/requests/models.py index 75f16e32..cdc17563 100644 --- a/requests/models.py +++ b/requests/models.py @@ -593,6 +593,7 @@ class Response(object): self._content = False self._content_consumed = False + self._next = None #: Integer Code of responded HTTP Status, e.g. 404 or 200. self.status_code = None @@ -706,12 +707,17 @@ class Response(object): @property def is_permanent_redirect(self): - """True if this Response one of the permanent versions of redirect""" + """True if this Response one of the permanent versions of redirect.""" return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect)) + @property + def next(self): + """Returns a PreparedRequest for the next request in a redirect chain, if there is one.""" + return self._next + @property def apparent_encoding(self): - """The apparent encoding, provided by the chardet library""" + """The apparent encoding, provided by the chardet library.""" return chardet.detect(self.content)['encoding'] def iter_content(self, chunk_size=1, decode_unicode=False): diff --git a/requests/sessions.py b/requests/sessions.py index 3ae42f99..1028bb7f 100755 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -114,8 +114,8 @@ class SessionRedirectMixin(object): return None def resolve_redirects(self, resp, req, stream=False, timeout=None, - verify=True, cert=None, proxies=None, **adapter_kwargs): - """Receives a Response. Returns a generator of Responses.""" + verify=True, cert=None, proxies=None, yield_requests=False, **adapter_kwargs): + """Receives a Response. Returns a generator of Responses or Requests.""" hist = [] # keep track of history @@ -203,22 +203,26 @@ class SessionRedirectMixin(object): # Override the original request. req = prepared_request - resp = self.send( - req, - stream=stream, - timeout=timeout, - verify=verify, - cert=cert, - proxies=proxies, - allow_redirects=False, - **adapter_kwargs - ) + if yield_requests: + yield req + else: - extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) + resp = self.send( + req, + stream=stream, + timeout=timeout, + verify=verify, + cert=cert, + proxies=proxies, + allow_redirects=False, + **adapter_kwargs + ) - # extract redirect url, if any, for the next loop - url = self.get_redirect_target(resp) - yield resp + extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) + + # extract redirect url, if any, for the next loop + url = self.get_redirect_target(resp) + yield resp def rebuild_auth(self, prepared_request, response): """When being redirected we may want to strip authentication from the @@ -597,8 +601,7 @@ class Session(SessionRedirectMixin): return self.request('DELETE', url, **kwargs) def send(self, request, **kwargs): - """ - Send a given PreparedRequest. + """Send a given PreparedRequest. :rtype: requests.Response """ @@ -668,6 +671,13 @@ class Session(SessionRedirectMixin): r = history.pop() r.history = history + # If redirects aren't being followed, store the response on the Request for Response.next(). + if not allow_redirects: + try: + r._next = self.resolve_redirects(r, request, yield_requests=True, **kwargs).next() + except StopIteration: + pass + if not stream: r.content