Can't get the correct contextvar set in the request handler in middleware's dispatch method
See original GitHub issueChecklist
- The bug is reproducible against the latest release and/or
master
. - There are no similar issues or pull requests to fix it yet.
Describe the bug
I try to manage database session with ContextVar
and want to close it in the middleware, but I always get none
unless the session was set in the middleware (This is valid, but not all handlers require sqlalchemy session).
To reproduce
from contextvars import ContextVar
from fastapi import Request
from sqlalchemy.orm import Session
from sqlalchemy import create_engine
from starlette.middleware.base import BaseHTTPMiddleware
from src.config import settings
engine = create_engine(
settings.SQLALCHEMY_DATABASE_URI,
)
session_var = ContextVar("session", default=None)
def get_session() -> Session:
if (rst := session_var.get()) is None:
rst = Session(engine, future=True)
print("create a session: ", rst)
session_var.set(rst)
print("return a session: ", rst)
return rst
class DBSessionMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# with get_session().begin():
# pass
res = await call_next(request)
# FIXME Can't get the correct contextvar, unless session is set here.
print("session in context: ", session_var.get())
if (session := session_var.get()) is not None:
session.close()
print("close the session: ", session)
return res
Expected behavior
Get the session if it is used in the handler, close it
Actual behavior
Always get none
Debugging material
Environment
- OS: WSL 2/Ubuntu 20.04
- Python version: 3.8.5
- Starlette version: 0.13.6 (via FastAP 0.61.1I)
Additional context
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
Middleware - Starlette
The Starlette application class allows you to include the ASGI middleware in a way that ensures that it remains wrapped by the exception...
Read more >Release 0.3.5 Tomasz Wojcik - starlette-context
Here an example of a plugin that extracts a Session from the request cookies, expects it to be encoded in base64, attempts to...
Read more >fastapi-events - PyPI
An event dispatching/handling library for FastAPI, and Starlette. Features: straightforward API to emit events anywhere in your code; events are handled ...
Read more >why do you need to bind a function in a constructor
handleChange = , can't I just use static functions for handleChange and call it directly with in the class onClick={handleRefreshClick}> ? I have...
Read more >httprouter - Go Packages
Package httprouter is a trie based high performance HTTP request ... and per handler support (using closure) e.g. GET(path,middleware.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Hi @cglacet,
The main advantage of using
contextvars
is that you don’t need to passrequest
instance everywhere in order to access some ctx data.If take into account example above, you can access to
session
from any place and it will be context-bound:For more information please follow PEP-567
Hi @ShoorDay,
The problem not with
starlette
, there is a problem with how you usecontextvars
. Basically, when you set contextvar inside a child task it won’t be available at the parent.An example regarding this problem:
The result will be:
In order to make your code working using
contextvars
you should update code to smth like this:If you have any questions or maybe I missed smth, feel free to ask)