My goal is to extract some information from request and put it in some global context. First thing I tried was middleware function which does this
user_ctx: ContextVar[typing.Optional[UUID]] = ContextVar('user_ctx', default=None)
def save_user_ctx(request: Request):
uid = ... # logic that extracts user uid from request header
user_ctx.set(uid)
And I add this in some another middleware function for example my_middleware.
So it really sets the contexts but as far as I see middleware works in another thread, so if I try something like
@router.post('/some_url', response_model=SomeResponseModel)
def some_url(data: SomeRequestModel, auth_checker = Depends(my_middleware)):
user_ctx.get() # >> None
auth_checker has all auth info, so middleware works okay. But uid = user_ctx.get() returns None.
This is just an example. Please
What I want to achieve is to store some context from request in thread which serves endpoints automatically. I mean without writing ctx.set(smth) as the first line of each endpoint.
I also tried to write decorator
def save_request_ctx(func):
@wraps(func)
def wrap(*args, **kwargs):
ctx.set(...)
return func(*args, **kwargs)
return wrap
But if endpoint doesnt have request: Request as parameter it gets - it doesnt appear in either args or kwargs. So, also, if you can tell how to force each endpoint to have request as parameter without manually adding it in each endpoint function - it would also be accepted as solution.
If my explanation of what I want is complicated I'll try to clarify it.
You might want to use my
starlette-contextfor that.In order to achieve what you want it'd be best if you subclassed
ContextMiddlewareand overwrote theset_contextmethod. What's returned will then be available in thecontextobject that you can import anywhere.Example code
After you register this middleware, in your view/logger you can import
and use
context["from_middleware"].Notice that I prepared "plugins" for most common use cases. If you want to access request/correlation id anywhere in your app, just init middleware with
FastAPI uses Starlette interface so you should be good to go.
Regarding
I can't answer that as I never tried using a view without a request argument.
Edit: I added
RawContextMiddlewarethat doesn't need the request object.