Skip to content

Commit 19724dd

Browse files
committed
Raise TooManyRedirects error when client gets redirected too many times
Closes aio-libs#2631
1 parent 55a6782 commit 19724dd

File tree

5 files changed

+34
-9
lines changed

5 files changed

+34
-9
lines changed

CHANGES/2631.feature

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raise ``TooManyRedirects`` exception when client gets redirected too many times
2+
instead of returning last response.

aiohttp/client.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
from . import hdrs, http, payload
1919
from .client_exceptions import * # noqa
2020
from .client_exceptions import (ClientError, ClientOSError, InvalidURL,
21-
ServerTimeoutError, WSServerHandshakeError)
21+
ServerTimeoutError, TooManyRedirects,
22+
WSServerHandshakeError)
2223
from .client_reqrep import * # noqa
2324
from .client_reqrep import ClientRequest, ClientResponse, _merge_ssl_params
2425
from .client_ws import ClientWebSocketResponse
@@ -360,7 +361,8 @@ async def _request(self, method, url, *,
360361
history.append(resp)
361362
if max_redirects and redirects >= max_redirects:
362363
resp.close()
363-
break
364+
raise TooManyRedirects(
365+
history[0].request_info, tuple(history))
364366
else:
365367
resp.release()
366368

aiohttp/client_exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class ClientHttpProxyError(ClientResponseError):
9393
"""
9494

9595

96+
class TooManyRedirects(ClientResponseError):
97+
"""Client was redirected too many times."""
98+
99+
96100
class ClientConnectionError(ClientError):
97101
"""Base class for client socket errors."""
98102

docs/client_reference.rst

+18-3
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ The client session supports the context manager protocol for self closing.
251251
:param bool allow_redirects: If set to ``False``, do not follow redirects.
252252
``True`` by default (optional).
253253

254+
:param int max_redirects: Maximum number of redirects to follow.
255+
``10`` by default.
256+
254257
:param bool compress: Set to ``True`` if request has to be compressed
255258
with deflate encoding. If `compress` can not be combined
256259
with a *Content-Encoding* and *Content-Length* headers.
@@ -501,7 +504,7 @@ The client session supports the context manager protocol for self closing.
501504

502505
:param bool autoclose: Automatically close websocket connection on close
503506
message from server. If *autoclose* is False
504-
them close procedure has to be handled manually.
507+
then close procedure has to be handled manually.
505508
``True`` by default
506509

507510
:param bool autoping: automatically send *pong* on *ping*
@@ -514,7 +517,7 @@ The client session supports the context manager protocol for self closing.
514517
reception.(optional)
515518

516519
:param str origin: Origin header to send to server(optional)
517-
520+
518521
:param dict headers: HTTP Headers to send with
519522
the request (optional)
520523

@@ -565,7 +568,7 @@ The client session supports the context manager protocol for self closing.
565568
authority channel, supported SSL options etc.
566569

567570
.. versionadded:: 2.3
568-
571+
569572
.. deprecated:: 3.0
570573

571574
Use ``ssl=ssl_context``
@@ -1727,6 +1730,18 @@ Response errors
17271730

17281731
.. versionadded:: 2.3
17291732

1733+
1734+
.. class:: TooManyRedirects
1735+
1736+
Client was redirected too many times.
1737+
1738+
Maximum number of redirects can be configured by using
1739+
parameter ``max_redirects`` in :meth:`request<aiohttp.ClientSession.request>`.
1740+
1741+
Derived from :exc:`ClientResponseError`
1742+
1743+
.. versionadded:: 3.2
1744+
17301745
Connection errors
17311746
^^^^^^^^^^^^^^^^^
17321747

tests/test_client_functional.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import aiohttp
1717
from aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web
1818
from aiohttp.abc import AbstractResolver
19+
from aiohttp.client_exceptions import TooManyRedirects
1920
from aiohttp.test_utils import unused_port
2021

2122

@@ -914,10 +915,11 @@ async def redirect(request):
914915
app.router.add_get(r'/redirect/{count:\d+}', redirect)
915916
client = await aiohttp_client(app)
916917

917-
resp = await client.get('/redirect/5', max_redirects=2)
918-
assert 302 == resp.status
919-
assert 2 == len(resp.history)
920-
resp.close()
918+
with pytest.raises(TooManyRedirects) as ctx:
919+
await client.get('/redirect/5', max_redirects=2)
920+
assert 2 == len(ctx.value.history)
921+
assert ctx.value.request_info.url.path == '/redirect/5'
922+
assert ctx.value.request_info.method == 'GET'
921923

922924

923925
async def test_HTTP_200_GET_WITH_PARAMS(aiohttp_client):

0 commit comments

Comments
 (0)