Contextvars are not reset between requests if the request contains multipart form data #2312
-
Hi Starlette team, we are experiencing an issue with Starlette where I constructed a minimal example which sets a context var in a middleware and resets it after the app has been called. It also raises an exception if the var is already set: import contextvars
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.responses import JSONResponse
from starlette.routing import Route
var = contextvars.ContextVar("var", default=None)
class ASGIMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
if scope["type"] != "http":
return await self.app(scope, receive, send)
if var.get() is not None:
raise ValueError(f"var is already set {var.get}")
token = var.set("TEST")
await self.app(scope, receive, send)
var.reset(token)
async def route(request):
return JSONResponse({"hello": "world"})
app = Starlette(
middleware=[Middleware(ASGIMiddleware)],
routes=[Route('/', route, methods=["POST"])]
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main_starlette:app",
host="0.0.0.0",
port=8001,
) Then, I execute a second script which calls this endpoint using a import httpx
if __name__ == "__main__":
url = "http://localhost:8001/"
files = {'file': open('./test.yaml', 'rb')}
with httpx.Client() as client:
for i in range(2):
r = client.post(url, timeout=None, files=files)
assert r.status_code == 200 This results in a server error due to the fact that the variable is already set (sometimes it is necessary to run the client script multiple times as the issue does not always occur). If I execute the same script without multipart data, it works without issues: ...
r = client.post(url, timeout=None)
... We have also experienced this issue without sending multipart form data for requests within the same client session but it occurs significantly less often and unfortunately I am not able to reproduce it consistently. We experienced this issue with Python 3.9 and 3.10, Starlette v0.31.1, and uvicorn v0.23.2. |
Beta Was this translation helpful? Give feedback.
#2335 (comment)