diff --git a/httpcore/__init__.py b/httpcore/__init__.py index b81c8779..d9c1364c 100644 --- a/httpcore/__init__.py +++ b/httpcore/__init__.py @@ -13,6 +13,7 @@ from .exceptions import ( ResponseClosed, StreamConsumed, Timeout, + TooManyRedirects ) from .interfaces import Adapter from .models import URL, Headers, Origin, Request, Response diff --git a/tests/adapters/test_redirects.py b/tests/adapters/test_redirects.py index f4a98105..dbcb2338 100644 --- a/tests/adapters/test_redirects.py +++ b/tests/adapters/test_redirects.py @@ -1,6 +1,7 @@ import pytest +from urllib.parse import parse_qs -from httpcore import Adapter, RedirectAdapter, Request, Response, codes +from httpcore import Adapter, RedirectAdapter, Request, Response, TooManyRedirects, codes class MockDispatch(Adapter): @@ -14,6 +15,13 @@ class MockDispatch(Adapter): ) elif request.url.path == "/relative_redirect": return Response(codes.see_other, headers=[(b"location", b"/")]) + elif request.url.path == "/multiple_redirects": + params = parse_qs(request.url.query) + count = int(params.get("count", "0")[0]) + code = codes.see_other if count else codes.ok + location = "/multiple_redirects?count=" + str(count - 1) + headers = [(b"location", location.encode())] if count else [] + return Response(code, headers=headers) return Response(codes.ok, body=b"Hello, world!") @@ -29,3 +37,17 @@ async def test_relative_redirect(): client = RedirectAdapter(MockDispatch()) response = await client.request("GET", "https://example.org/relative_redirect") assert response.status_code == codes.ok + + +@pytest.mark.asyncio +async def test_multiple_redirects(): + client = RedirectAdapter(MockDispatch()) + response = await client.request("GET", "https://example.org/multiple_redirects?count=20") + assert response.status_code == codes.ok + + +@pytest.mark.asyncio +async def test_too_many_redirects(): + client = RedirectAdapter(MockDispatch()) + with pytest.raises(TooManyRedirects): + await client.request("GET", "https://example.org/multiple_redirects?count=21")