Skip to content

Commit 4000013

Browse files
committed
Merge pull request #614 from knitori/master
Collect history of responses if redirects occur.
2 parents 5622139 + 4e586c8 commit 4000013

File tree

5 files changed

+55
-0
lines changed

5 files changed

+55
-0
lines changed

aiohttp/client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ def _request(self, method, url, *,
141141
raise RuntimeError('Session is closed')
142142

143143
redirects = 0
144+
history = []
144145
if not isinstance(method, upstr):
145146
method = upstr(method)
146147

@@ -193,6 +194,7 @@ def _request(self, method, url, *,
193194
# redirects
194195
if resp.status in (301, 302, 303, 307) and allow_redirects:
195196
redirects += 1
197+
history.append(resp)
196198
if max_redirects and redirects >= max_redirects:
197199
resp.close(force=True)
198200
break
@@ -221,6 +223,7 @@ def _request(self, method, url, *,
221223

222224
break
223225

226+
resp.history = history
224227
return resp
225228

226229
def ws_connect(self, url, *,

aiohttp/client_reqrep.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ class ClientResponse:
512512
cookies = None # Response cookies (Set-Cookie)
513513
content = None # Payload stream
514514
headers = None # Response headers, CIMultiDictProxy
515+
history = None # List of responses, if redirects occured
515516

516517
_connection = None # current connection
517518
flow_control_class = FlowControlStreamReader # reader flow control

docs/client.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,22 @@ If a response contains some Cookies, you can quickly access them::
527527
<aiohttp-client-session>` object.
528528

529529

530+
Response History
531+
----------------
532+
533+
If a request was redirected, it is possible to view previous responses using
534+
the history attribute::
535+
536+
>>> r = await aiohttp.get('http://example.com/some/redirect/')
537+
>>> r
538+
<ClientResponse(http://example.com/some/other/url/) [200]>
539+
>>> r.history
540+
[<ClientResponse(http://example.com/some/redirect/) [301]>]
541+
542+
If no redirects occured or ``allow_redirects`` is set to ``False``, history will
543+
be an empty list.
544+
545+
530546
Timeouts
531547
--------
532548

docs/client_reference.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,11 @@ Response object
954954

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

957+
.. attribute:: history
958+
959+
:class:`list` of :class:`ClientResponse` objects of preceding requests, if there
960+
were redirects.
961+
957962
.. method:: close()
958963

959964
Close response and underlying connection.

tests/test_client_functional.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,33 @@ def handler(request):
333333
assert 200 == resp.status
334334
finally:
335335
yield from resp.release()
336+
337+
338+
@pytest.mark.run_loop
339+
def test_history(create_app_and_client):
340+
@asyncio.coroutine
341+
def handler_redirect(request):
342+
return web.Response(status=301, headers={'Location': '/ok'})
343+
344+
@asyncio.coroutine
345+
def handler_ok(request):
346+
return web.Response(status=200)
347+
348+
app, client = yield from create_app_and_client()
349+
app.router.add_route('GET', '/ok', handler_ok)
350+
app.router.add_route('GET', '/redirect', handler_redirect)
351+
352+
resp = yield from client.get('/ok')
353+
try:
354+
assert resp.history == []
355+
assert resp.status == 200
356+
finally:
357+
resp.release()
358+
359+
resp_redirect = yield from client.get('/redirect')
360+
try:
361+
assert len(resp_redirect.history) == 1
362+
assert resp_redirect.history[0].status == 301
363+
assert resp_redirect.status == 200
364+
finally:
365+
resp_redirect.release()

0 commit comments

Comments
 (0)