Can't use http middleware
rahul-agarwal-savii opened this issue · 1 comments
I tried using starlette-context
and it solves most of my problems as a near to perfect equivalent for Flask g.
Now I am facing issue in setting the request_id in the FastAPI's "http" middleware, my main.py is as follows:
import uuid
from fastapi import FastAPI, Request
from fastapi.encoders import jsonable_encoder
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from starlette_context import context
from starlette_context.middleware import RawContextMiddleware
from app.api.auth import security_router
from app.api.health import status_router
from app.api.v1.router import v1_router
from app.core.config import settings
from app.database import Base, engine
from app.exceptions import CustomException
def get_application():
_app = FastAPI(title="referral-service")
allowed_origins = [str(origin) for origin in settings.BACKEND_CORS_ORIGINS]
_app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
_app.add_middleware(RawContextMiddleware)
_app.include_router(v1_router, prefix="/api/v1")
_app.include_router(security_router)
_app.include_router(status_router)
return _app
app = get_application()
@app.on_event("startup")
async def startup():
# create db tables
async with engine.begin() as conn:
# await conn.run_sync(Base.metadata.drop_all)
await conn.run_sync(Base.metadata.create_all)
@app.middleware("http")
async def set_request_context(request: Request, call_next):
request_id = uuid.uuid4()
context["request_id"] = request_id
response = await call_next(request)
return response
@app.exception_handler(CustomException)
async def custom_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
jsonable_encoder(exc.response), status_code=exc.status_code
)
When i run any of my route, it sends me the following error:
Traceback (most recent call last):
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py", line 366, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/fastapi/applications.py", line 261, in __call__
await super().__call__(scope, receive, send)
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/starlette/applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/starlette/middleware/errors.py", line 181, in __call__
raise exc
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/starlette/middleware/base.py", line 63, in __call__
response = await self.dispatch_func(request, call_next)
File "/Users/rahulagarwal/savii-code/referral-service/./app/main.py", line 58, in set_request_context
context["request_id"] = request_id
File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/collections/__init__.py", line 1061, in __setitem__
self.data[key] = item
File "/Users/rahulagarwal/Library/Caches/pypoetry/virtualenvs/referral-service-bzkw0PDN-py3.9/lib/python3.9/site-packages/starlette_context/ctx.py", line 35, in data
raise ContextDoesNotExistError
starlette_context.errors.ContextDoesNotExistError: You didn't use the required middleware or you're trying to access `context` object outside of the request-response cycle.
Am i doing something wrong with this? As far as I understand the middleware is a part of request-response cycle, so why am I getting the error that this is not part of the request-response cycle. Please help
Probably your set_request_context
middleware is executed before the RawContextMiddleware.
There are plugins to populate the context with headers, especially request-id, you don't have to reinvent that.
https://starlette-context.readthedocs.io/en/latest/plugins.html