When making outgoing HTTP calls to downstream services, the correlation ID
should be propagated so that the entire request chain can be traced. The
library provides both wrapper functions and reusable transports for httpx
that handle this automatically.
Note: httpx is an optional dependency. Install it separately:
pip install httpx
Choosing an approach
Use the wrapper functions when requests are made ad hoc and the call site
already controls the httpx.request(...) invocation. Use the transport classes
when the application relies on shared httpx.Client or httpx.AsyncClient
instances and wants correlation header injection to happen transparently for
every request sent through that client.
Synchronous wrapper usage
Use request_with_correlation_id as a drop-in replacement for httpx.request:
from falcon_correlate import request_with_correlation_id
# The correlation ID header is injected automatically
# when correlation_id_var is set (e.g. during a Falcon request).
response = request_with_correlation_id("GET", "https://api.example.com/data")
All keyword arguments are passed through to httpx.request:
response = request_with_correlation_id(
"POST",
"https://api.example.com/submit",
json={"key": "value"},
headers={"Authorization": "Bearer token"},
timeout=10,
)
Asynchronous wrapper usage
Use async_request_with_correlation_id for async code:
from falcon_correlate import async_request_with_correlation_id
response = await async_request_with_correlation_id(
"GET", "https://api.example.com/data"
)
The async variant creates a temporary httpx.AsyncClient for each call.
HTTP client behaviour
- When
correlation_id_varis set (i.e. during a Falcon request handled byCorrelationIDMiddleware), theX-Correlation-IDheader is added to the outgoing request. - When
correlation_id_varis not set (e.g. outside request handling), no header is added. - Existing headers passed by the caller are always preserved. The correlation ID header is added alongside them, never replacing them.
- If the caller explicitly sets the correlation header itself, both the wrapper functions and the transport classes keep the caller's value.