import asyncio from uuid import UUID import httpx from app.config import Settings from app.controllers.v1.delivery import get_aggregator_service from app.main import create_app from app.schemas.request import DeliveryRequest class StubAggregatorService: def __init__(self) -> None: self.calls: list[DeliveryRequest] = [] async def get_all_prices(self, request: DeliveryRequest) -> list[object]: self.calls.append(request) return [] def _build_payload() -> dict[str, object]: return { "entity": "individual", "from_city": "Moscow", "to_city": "Kazan", "weight_kg": 2.5, "length_cm": 30.0, "width_cm": 20.0, "height_cm": 10.0, } def _build_app( *, request_id_header: str, service: StubAggregatorService, ) -> tuple[object, StubAggregatorService]: settings = Settings( controller={"request_id_header": request_id_header}, observability={ "service_name": "g2s-tests", "otlp_endpoint": "", "log_level": "INFO", }, ) app = create_app(settings=settings) async def override_service() -> StubAggregatorService: return service app.dependency_overrides[get_aggregator_service] = override_service return app, service def test_request_id_is_generated_per_request_and_returned_in_header() -> None: app, service = _build_app( request_id_header="X-Request-ID", service=StubAggregatorService(), ) async def run_requests() -> tuple[httpx.Response, httpx.Response]: transport = httpx.ASGITransport(app=app) async with httpx.AsyncClient( transport=transport, base_url="http://testserver", ) as client: first = await client.post("/api/v1/delivery/price", json=_build_payload()) second = await client.post("/api/v1/delivery/price", json=_build_payload()) return first, second first_response, second_response = asyncio.run(run_requests()) assert first_response.status_code == 200 assert second_response.status_code == 200 first_request_id = first_response.headers["X-Request-ID"] second_request_id = second_response.headers["X-Request-ID"] assert UUID(first_request_id).version == 4 assert UUID(second_request_id).version == 4 assert first_request_id != second_request_id assert len(service.calls) == 2 def test_request_id_uses_configured_header_name() -> None: app, _ = _build_app( request_id_header="X-Correlation-ID", service=StubAggregatorService(), ) async def run_request() -> httpx.Response: transport = httpx.ASGITransport(app=app) async with httpx.AsyncClient( transport=transport, base_url="http://testserver", ) as client: return await client.post("/api/v1/delivery/price", json=_build_payload()) response = asyncio.run(run_request()) assert response.status_code == 200 assert "X-Correlation-ID" in response.headers assert "X-Request-ID" not in response.headers