import pytest
from eggfetch.compat.httpx import (
Auth,
AsyncClient,
Client,
MockTransport,
Request,
Response,
)
class TestPerHopOrdering:
def test_direct_request_order(self):
event_log = []
def on_request(request):
event_log.append(("request_hook", request.headers.get("x-step", "none")))
def on_response(response):
event_log.append(("response_hook", response.status_code))
def handler(request):
return Response(
200,
headers=[("Set-Cookie", "hop1=yes; Path=/")],
text="ok",
)
with Client(
transport=MockTransport(handler),
event_hooks={"request": [on_request], "response": [on_response]},
) as c:
resp = c.get("http://testserver/")
assert resp.status_code == 200
assert event_log == [("request_hook", "none"), ("response_hook", 200)]
assert c.cookies.get("hop1") == "yes"
def test_redirect_order(self):
event_log = []
def on_request(request):
event_log.append(("request_hook", request.url.path))
def on_response(response):
event_log.append(("response_hook", response.status_code))
def handler(request):
if request.url.path == "/a":
return Response(
302,
headers=[
("Location", "/b"),
("Set-Cookie", "from_a=yes; Path=/"),
],
)
return Response(200, text="ok")
with Client(
transport=MockTransport(handler),
follow_redirects=True,
event_hooks={"request": [on_request], "response": [on_response]},
) as c:
resp = c.get("http://testserver/a")
assert resp.status_code == 200
assert event_log == [
("request_hook", "/a"),
("response_hook", 302),
("request_hook", "/b"),
("response_hook", 200),
]
assert c.cookies.get("from_a") == "yes"
def test_auth_then_redirect_order(self):
from eggfetch.compat.httpx import BasicAuth
event_log = []
def on_request(request):
event_log.append(("request_hook", request.url.path))
def on_response(response):
event_log.append(("response_hook", response.status_code))
def handler(request):
if request.url.path == "/protected" and request.headers.get("authorization"):
return Response(
302,
headers=[
("Location", "/final"),
("Set-Cookie", "auth_cookie=yes; Path=/"),
],
)
if request.url.path == "/final":
return Response(200, text="ok")
return Response(401)
with Client(
transport=MockTransport(handler),
auth=BasicAuth("user", "pass"),
follow_redirects=True,
event_hooks={"request": [on_request], "response": [on_response]},
) as c:
resp = c.get("http://testserver/protected")
assert resp.status_code == 200
assert event_log == [
("request_hook", "/protected"),
("response_hook", 302),
("request_hook", "/final"),
("response_hook", 200),
]
def test_each_hop_exactly_one_hook_call(self):
hop_count = [0]
def on_request(request):
hop_count[0] += 1
def on_response(response):
pass
def handler(request):
if request.url.path == "/a":
return Response(302, headers={"Location": "/b"})
if request.url.path == "/b":
return Response(302, headers={"Location": "/c"})
return Response(200)
with Client(
transport=MockTransport(handler),
follow_redirects=True,
event_hooks={"request": [on_request], "response": [on_response]},
) as c:
resp = c.get("http://testserver/a")
assert hop_count[0] == 3
class TestAsyncPerHopOrdering:
@pytest.mark.asyncio
async def test_redirect_order_async(self):
event_log = []
async def on_request(request):
event_log.append(("request_hook", request.url.path))
async def on_response(response):
event_log.append(("response_hook", response.status_code))
async def handler(request):
if request.url.path == "/a":
return Response(
302,
headers=[
("Location", "/b"),
("Set-Cookie", "from_a=yes; Path=/"),
],
)
return Response(200, text="ok")
async with AsyncClient(
async_transport=MockTransport(handler),
follow_redirects=True,
event_hooks={"request": [on_request], "response": [on_response]},
) as c:
resp = await c.get("http://testserver/a")
assert resp.status_code == 200
assert event_log == [
("request_hook", "/a"),
("response_hook", 302),
("request_hook", "/b"),
("response_hook", 200),
]
@pytest.mark.asyncio
async def test_auth_redirect_order_async(self):
from eggfetch.compat.httpx import BasicAuth
event_log = []
async def on_request(request):
event_log.append(("request_hook", request.url.path))
async def on_response(response):
event_log.append(("response_hook", response.status_code))
async def handler(request):
if request.url.path == "/protected" and request.headers.get("authorization"):
return Response(302, headers=[("Location", "/final")])
if request.url.path == "/final":
return Response(200, text="ok")
return Response(401)
async with AsyncClient(
async_transport=MockTransport(handler),
auth=BasicAuth("user", "pass"),
follow_redirects=True,
event_hooks={"request": [on_request], "response": [on_response]},
) as c:
resp = await c.get("http://testserver/protected")
assert resp.status_code == 200
assert event_log == [
("request_hook", "/protected"),
("response_hook", 302),
("request_hook", "/final"),
("response_hook", 200),
]