| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- import logging
- from typing import Any
- import httpx
- logger = logging.getLogger("app.http")
- _MAX_BODY_LOG_LENGTH = 2000
- def _truncate(text: str, max_len: int = _MAX_BODY_LOG_LENGTH) -> str:
- if len(text) <= max_len:
- return text
- return text[:max_len] + f"... (truncated, total {len(text)} chars)"
- def _on_request(request: httpx.Request) -> None:
- body = request.content.decode("utf-8", errors="replace") if request.content else ""
- logger.info(
- "[HTTP >>> ] %s %s | body(%d): %s",
- request.method,
- request.url,
- len(body),
- _truncate(body),
- )
- def _on_response(response: httpx.Response) -> None:
- response.read()
- logger.info(
- "[HTTP <<< ] %s %s | body(%d): %s",
- response.status_code,
- response.url,
- len(response.text),
- _truncate(response.text),
- )
- def logged_client(**kwargs: Any) -> httpx.Client:
- """Create an ``httpx.Client`` that logs every request body and response body."""
- hooks = kwargs.pop("event_hooks", {})
- req_hooks = list(hooks.get("request", []))
- resp_hooks = list(hooks.get("response", []))
- req_hooks.append(_on_request)
- resp_hooks.append(_on_response)
- kwargs["event_hooks"] = {"request": req_hooks, "response": resp_hooks}
- return httpx.Client(**kwargs)
|