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-context
for that.In order to achieve what you want it'd be best if you subclassed
ContextMiddleware
and overwrote theset_context
method. What's returned will then be available in thecontext
object 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
RawContextMiddleware
that doesn't need the request object.