client = httpx.Client(event_hooks={'response': [raise_on_4xx_5xx]})
```
+!!! note
+ Response event hooks are called before determining if the response body
+ should be read or not.
+
+ If you need access to the response body inside an event hook, you'll
+ need to call `response.read()`.
+
The hooks are also allowed to modify `request` and `response` objects.
```python
def add_timestamp(request):
request.headers['x-request-timestamp'] = datetime.now(tz=datetime.utc).isoformat()
-
+
client = httpx.Client(event_hooks={'request': [add_timestamp]})
```
if not stream:
response.read()
- for hook in self._event_hooks["response"]:
- hook(response)
-
return response
except Exception as exc:
try:
request = next(auth_flow)
- for hook in self._event_hooks["request"]:
- hook(request)
-
while True:
response = self._send_handling_redirects(
request,
"Exceeded maximum allowed redirects.", request=request
)
+ for hook in self._event_hooks["request"]:
+ hook(request)
+
response = self._send_single_request(request, timeout)
try:
+ for hook in self._event_hooks["response"]:
+ hook(response)
response.history = list(history)
if not response.is_redirect:
if not stream:
await response.aread()
- for hook in self._event_hooks["response"]:
- await hook(response)
-
return response
- except Exception as exc:
+ except Exception as exc: # pragma: no cover
await response.aclose()
raise exc
try:
request = await auth_flow.__anext__()
- for hook in self._event_hooks["request"]:
- await hook(request)
-
while True:
response = await self._send_handling_redirects(
request,
"Exceeded maximum allowed redirects.", request=request
)
+ for hook in self._event_hooks["request"]:
+ await hook(request)
+
response = await self._send_single_request(request, timeout)
try:
+ for hook in self._event_hooks["response"]:
+ await hook(response)
+
response.history = list(history)
if not response.is_redirect:
def test_event_hooks_with_redirect():
"""
- A redirect request should not trigger a second 'request' event hook.
+ A redirect request should trigger additional 'request' and 'response' event hooks.
"""
events = []
http.get("http://127.0.0.1:8000/redirect", auth=("username", "password"))
assert events == [
+ {
+ "event": "request",
+ "headers": {
+ "host": "127.0.0.1:8000",
+ "user-agent": f"python-httpx/{httpx.__version__}",
+ "accept": "*/*",
+ "accept-encoding": "gzip, deflate, br",
+ "connection": "keep-alive",
+ "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=",
+ },
+ },
+ {
+ "event": "response",
+ "headers": {"location": "/", "server": "testserver"},
+ },
{
"event": "request",
"headers": {
@pytest.mark.usefixtures("async_environment")
async def test_async_event_hooks_with_redirect():
"""
- A redirect request should not trigger a second 'request' event hook.
+ A redirect request should trigger additional 'request' and 'response' event hooks.
"""
events = []
await http.get("http://127.0.0.1:8000/redirect", auth=("username", "password"))
assert events == [
+ {
+ "event": "request",
+ "headers": {
+ "host": "127.0.0.1:8000",
+ "user-agent": f"python-httpx/{httpx.__version__}",
+ "accept": "*/*",
+ "accept-encoding": "gzip, deflate, br",
+ "connection": "keep-alive",
+ "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=",
+ },
+ },
+ {
+ "event": "response",
+ "headers": {"location": "/", "server": "testserver"},
+ },
{
"event": "request",
"headers": {