Fix stream not read error for files whose recieved from bot.

This commit is contained in:
febux 2026-09-06 20:41:35 +03:00
parent 85db70887d
commit 1c08e7362c
2 changed files with 42 additions and 1 deletions

View file

@ -147,13 +147,20 @@ def http_log_event_hooks(
request.extensions[started_key] = time.perf_counter() request.extensions[started_key] = time.perf_counter()
if not is_debug_enabled(): if not is_debug_enabled():
return return
try:
body: bytes | str | None = request.content
except httpx.RequestNotRead:
# Streaming bodies (e.g. multipart file uploads) are never loaded
# into memory, so there is nothing to inspect without consuming
# the stream the actual send needs. Summarize instead of crashing.
body = "<streaming body not read>"
log.debug( log.debug(
"http_request", "http_request",
service=service, service=service,
method=request.method, method=request.method,
url=str(request.url), url=str(request.url),
headers=redact_headers(request.headers), headers=redact_headers(request.headers),
body=safe_body(request.content, request.headers.get("content-type"), max_payload_chars), body=safe_body(body, request.headers.get("content-type"), max_payload_chars),
) )
async def _log_response(response: httpx.Response) -> None: async def _log_response(response: httpx.Response) -> None:

View file

@ -145,3 +145,37 @@ async def test_event_hooks_silent_without_debug(monkeypatch: pytest.MonkeyPatch)
await client.get("https://api.test/v1/things") await client.get("https://api.test/v1/things")
assert logs == [] assert logs == []
async def test_event_hooks_handle_streaming_multipart_body(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Multipart uploads stream their body; the request hook must not crash."""
monkeypatch.setattr(hhttp, "is_debug_enabled", lambda: True)
_config = structlog.get_config()
monkeypatch.setattr(
hhttp,
"get_logger",
lambda name: structlog.get_logger(name),
)
structlog.configure(
processors=_config["processors"],
wrapper_class=structlog.stdlib.BoundLogger,
logger_factory=_config["logger_factory"],
cache_logger_on_first_use=False,
)
with capture_logs() as logs:
transport = httpx.MockTransport(lambda request: httpx.Response(202, json={"ok": True}))
async with httpx.AsyncClient(
transport=transport,
event_hooks=http_log_event_hooks(service="test-svc"),
) as client:
response = await client.post(
"https://api.test/v1/documents",
files={"file": ("contract.pdf", b"%PDF-1.7 fake", "application/pdf")},
)
assert response.status_code == 202
request_entry = next(entry for entry in logs if entry.get("event") == "http_request")
assert request_entry["method"] == "POST"
assert request_entry["body"] == "<streaming body not read>"