Skip to content

Commit

Permalink
Merge pull request #614 from knitori/master
Browse files Browse the repository at this point in the history
Collect history of responses if redirects occur.
  • Loading branch information
asvetlov committed Nov 3, 2015
2 parents 5622139 + 4e586c8 commit 4000013
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 0 deletions.
3 changes: 3 additions & 0 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def _request(self, method, url, *,
raise RuntimeError('Session is closed')

redirects = 0
history = []
if not isinstance(method, upstr):
method = upstr(method)

Expand Down Expand Up @@ -193,6 +194,7 @@ def _request(self, method, url, *,
# redirects
if resp.status in (301, 302, 303, 307) and allow_redirects:
redirects += 1
history.append(resp)
if max_redirects and redirects >= max_redirects:
resp.close(force=True)
break
Expand Down Expand Up @@ -221,6 +223,7 @@ def _request(self, method, url, *,

break

resp.history = history
return resp

def ws_connect(self, url, *,
Expand Down
1 change: 1 addition & 0 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ class ClientResponse:
cookies = None # Response cookies (Set-Cookie)
content = None # Payload stream
headers = None # Response headers, CIMultiDictProxy
history = None # List of responses, if redirects occured

_connection = None # current connection
flow_control_class = FlowControlStreamReader # reader flow control
Expand Down
16 changes: 16 additions & 0 deletions docs/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,22 @@ If a response contains some Cookies, you can quickly access them::
<aiohttp-client-session>` object.


Response History
----------------

If a request was redirected, it is possible to view previous responses using
the history attribute::

>>> r = await aiohttp.get('http://example.com/some/redirect/')
>>> r
<ClientResponse(http://example.com/some/other/url/) [200]>
>>> r.history
[<ClientResponse(http://example.com/some/redirect/) [301]>]

If no redirects occured or ``allow_redirects`` is set to ``False``, history will
be an empty list.


Timeouts
--------

Expand Down
5 changes: 5 additions & 0 deletions docs/client_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,11 @@ Response object

HTTP headers of response, :class:`CIMultiDictProxy`.

.. attribute:: history

:class:`list` of :class:`ClientResponse` objects of preceding requests, if there
were redirects.

.. method:: close()

Close response and underlying connection.
Expand Down
30 changes: 30 additions & 0 deletions tests/test_client_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,33 @@ def handler(request):
assert 200 == resp.status
finally:
yield from resp.release()


@pytest.mark.run_loop
def test_history(create_app_and_client):
@asyncio.coroutine
def handler_redirect(request):
return web.Response(status=301, headers={'Location': '/ok'})

@asyncio.coroutine
def handler_ok(request):
return web.Response(status=200)

app, client = yield from create_app_and_client()
app.router.add_route('GET', '/ok', handler_ok)
app.router.add_route('GET', '/redirect', handler_redirect)

resp = yield from client.get('/ok')
try:
assert resp.history == []
assert resp.status == 200
finally:
resp.release()

resp_redirect = yield from client.get('/redirect')
try:
assert len(resp_redirect.history) == 1
assert resp_redirect.history[0].status == 301
assert resp_redirect.status == 200
finally:
resp_redirect.release()

0 comments on commit 4000013

Please sign in to comment.