diff --git a/README.md b/README.md index 8d8470b..45e16dc 100644 --- a/README.md +++ b/README.md @@ -59,13 +59,18 @@ from fastapi import FastAPI from asgi_correlation_id import CorrelationIdMiddleware app = FastAPI() -app.add_middleware(CorrelationIdMiddleware) +app = CorrelationIdMiddleware(app) ``` or any other way your framework allows. For [Starlette](https://github.com/encode/starlette) apps, just substitute `FastAPI` with `Starlette` in all examples. +> **Note:** You can also use `app.add_middleware(CorrelationIdMiddleware)`, but be aware that this places the +> correlation ID middleware *inside* Starlette's `ServerErrorMiddleware`. This means the `X-Request-ID` header +> won't be included in `500` error responses. The wrapping approach shown above doesn't have this limitation. +> See [exception handling](#exception-handling) for more information. + ## Configure logging This section assumes you have already started configuring logging in your project. If this is not the case, check out @@ -146,8 +151,8 @@ If you're using a json log-formatter, just add `correlation-id: %(correlation_id The middleware can be configured in a few ways, but there are no required arguments. ```python -app.add_middleware( - CorrelationIdMiddleware, +app = CorrelationIdMiddleware( + app, header_name='X-Request-ID', update_request_header=True, generator=lambda: uuid4().hex, @@ -253,13 +258,16 @@ For more details on the topic, refer to the [CORS protocol](https://fetch.spec.w ## Exception handling -By default, the `X-Request-ID` response header will be included in all responses from the server, *except* in the case -of unhandled server errors. If you wish to include request IDs in the case of a `500` error you can add a custom -exception handler. +If you added the middleware using the recommended wrapping approach (`app = CorrelationIdMiddleware(app)`), the +`X-Request-ID` response header will be included in *all* responses, including unhandled `500` errors. No extra +configuration is needed. -Here are some simple examples to help you get started. See each framework's documentation for more info. +If you used `app.add_middleware(CorrelationIdMiddleware)` instead, the header will be missing from `500` responses +because Starlette's `ServerErrorMiddleware` catches the exception before the correlation ID middleware can add the +header. In that case, you can add a custom exception handler: -### Starlette +
+Starlette exception handler Docs: https://www.starlette.io/exceptions/ @@ -285,7 +293,10 @@ app = Starlette( ) ``` -### FastAPI +
+ +
+FastAPI exception handler Docs: https://fastapi.tiangolo.com/tutorial/handling-errors/ @@ -309,6 +320,8 @@ async def unhandled_exception_handler(request: Request, exc: Exception) -> JSONR )) ``` +
+ If you are using CORS, you also have to include the `Access-Control-Allow-Origin` and `Access-Control-Expose-Headers` headers in the error response. For more details, see the [CORS section](#cors) above. @@ -492,8 +505,7 @@ def configure_logging(): format="%(levelname)s log [%(correlation_id)s] %(name)s %(message)s") -app = FastAPI(on_startup=[configure_logging]) -app.add_middleware(asgi_correlation_id.CorrelationIdMiddleware) +fastapi_app = FastAPI(on_startup=[configure_logging]) router = APIRouter() @@ -504,7 +516,8 @@ async def test_get(): logger.info("test_get") -app.include_router(router) +fastapi_app.include_router(router) +app = asgi_correlation_id.CorrelationIdMiddleware(fastapi_app) if __name__ == "__main__": @@ -577,8 +590,7 @@ def configure_logging(): format="%(levelname)s log [%(correlation_id)s] %(name)s %(message)s") -app = FastAPI(on_startup=[configure_logging]) -app.add_middleware(asgi_correlation_id.CorrelationIdMiddleware) +fastapi_app = FastAPI(on_startup=[configure_logging]) router = APIRouter() @@ -588,7 +600,8 @@ async def test_get(): logger.info("test_get") -app.include_router(router) +fastapi_app.include_router(router) +app = asgi_correlation_id.CorrelationIdMiddleware(fastapi_app) if __name__ == "__main__":