Skip to content

Commit

Permalink
Raise TooManyRedirects error when client gets redirected too many tim…
Browse files Browse the repository at this point in the history
…es (#2943)

Closes #2631
  • Loading branch information
roganov authored and asvetlov committed Apr 17, 2018
1 parent af0994f commit 544716c
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES/2631.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Raise ``TooManyRedirects`` exception when client gets redirected too many times
instead of returning last response.
6 changes: 4 additions & 2 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
from . import hdrs, http, payload
from .client_exceptions import * # noqa
from .client_exceptions import (ClientError, ClientOSError, InvalidURL,
ServerTimeoutError, WSServerHandshakeError)
ServerTimeoutError, TooManyRedirects,
WSServerHandshakeError)
from .client_reqrep import * # noqa
from .client_reqrep import ClientRequest, ClientResponse, _merge_ssl_params
from .client_ws import ClientWebSocketResponse
Expand Down Expand Up @@ -360,7 +361,8 @@ async def _request(self, method, url, *,
history.append(resp)
if max_redirects and redirects >= max_redirects:
resp.close()
break
raise TooManyRedirects(
history[0].request_info, tuple(history))
else:
resp.release()

Expand Down
4 changes: 4 additions & 0 deletions aiohttp/client_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class ClientHttpProxyError(ClientResponseError):
"""


class TooManyRedirects(ClientResponseError):
"""Client was redirected too many times."""


class ClientConnectionError(ClientError):
"""Base class for client socket errors."""

Expand Down
21 changes: 18 additions & 3 deletions docs/client_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ The client session supports the context manager protocol for self closing.
:param bool allow_redirects: If set to ``False``, do not follow redirects.
``True`` by default (optional).

:param int max_redirects: Maximum number of redirects to follow.
``10`` by default.

:param bool compress: Set to ``True`` if request has to be compressed
with deflate encoding. If `compress` can not be combined
with a *Content-Encoding* and *Content-Length* headers.
Expand Down Expand Up @@ -501,7 +504,7 @@ The client session supports the context manager protocol for self closing.

:param bool autoclose: Automatically close websocket connection on close
message from server. If *autoclose* is False
them close procedure has to be handled manually.
then close procedure has to be handled manually.
``True`` by default

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

:param str origin: Origin header to send to server(optional)

:param dict headers: HTTP Headers to send with
the request (optional)

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

.. versionadded:: 2.3

.. deprecated:: 3.0

Use ``ssl=ssl_context``
Expand Down Expand Up @@ -1727,6 +1730,18 @@ Response errors

.. versionadded:: 2.3


.. class:: TooManyRedirects

Client was redirected too many times.

Maximum number of redirects can be configured by using
parameter ``max_redirects`` in :meth:`request<aiohttp.ClientSession.request>`.

Derived from :exc:`ClientResponseError`

.. versionadded:: 3.2

Connection errors
^^^^^^^^^^^^^^^^^

Expand Down
10 changes: 6 additions & 4 deletions tests/test_client_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import aiohttp
from aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web
from aiohttp.abc import AbstractResolver
from aiohttp.client_exceptions import TooManyRedirects
from aiohttp.test_utils import unused_port


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

resp = await client.get('/redirect/5', max_redirects=2)
assert 302 == resp.status
assert 2 == len(resp.history)
resp.close()
with pytest.raises(TooManyRedirects) as ctx:
await client.get('/redirect/5', max_redirects=2)
assert 2 == len(ctx.value.history)
assert ctx.value.request_info.url.path == '/redirect/5'
assert ctx.value.request_info.method == 'GET'


async def test_HTTP_200_GET_WITH_PARAMS(aiohttp_client):
Expand Down

0 comments on commit 544716c

Please sign in to comment.