httpx propagation

Updated Jul 20, 2026

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.

Transport usage with shared clients

Use CorrelationIDTransport for a reusable synchronous client:

import httpx
from falcon_correlate import CorrelationIDTransport

base_transport = httpx.HTTPTransport()

with httpx.Client(transport=CorrelationIDTransport(base_transport)) as client:
    response = client.get("https://api.example.com/data")

Use AsyncCorrelationIDTransport for a reusable async client:

import httpx
from falcon_correlate import AsyncCorrelationIDTransport

base_transport = httpx.AsyncHTTPTransport()

async with httpx.AsyncClient(
    transport=AsyncCorrelationIDTransport(base_transport)
) as client:
    response = await client.get("https://api.example.com/data")

The transport classes preserve an explicitly supplied correlation header on the outgoing request. If the caller already set X-Correlation-ID, falcon-correlate leaves that value unchanged.

HTTP client behaviour

  • When correlation_id_var is set (i.e. during a Falcon request handled by CorrelationIDMiddleware), the X-Correlation-ID header is added to the outgoing request.
  • When correlation_id_var is 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.