Description
Discussed in #1100
Originally posted by bunny-therapist January 29, 2024
I am running a FastAPI app using nginx unit, and using a python script to send multiple sequential (wait for response before sending next) requests to it with the "requests" library. When I reuse the same requests.Session
object for all the requests, so that requests.Session.close
is not called, then I get intermittent crashes in the application and thus status 500 back.
Traceback (most recent call last):
File "<path>/venv310/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "<path>/venv310/lib/python3.10/site-packages/starlette/applications.py", line 123, in __call__
await self.middleware_stack(scope, receive, send)
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/errors.py", line 186, in __call__
raise exc
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/errors.py", line 164, in __call__
await self.app(scope, receive, _send)
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 189, in __call__
with collapse_excgroups():
File "/usr/lib/python3.10/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "<path>/venv310/lib/python3.10/site-packages/starlette/_utils.py", line 91, in collapse_excgroups
raise exc
File "<path>/venv310/lib/python3.10/site-packages/starlette/responses.py", line 257, in wrap
await func()
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 217, in stream_response
return await super().stream_response(send)
File "<path>/venv310/lib/python3.10/site-packages/starlette/responses.py", line 246, in stream_response
async for chunk in self.body_iterator:
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 181, in body_stream
raise app_exc
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 151, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 189, in __call__
with collapse_excgroups():
File "/usr/lib/python3.10/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "<path>/venv310/lib/python3.10/site-packages/starlette/_utils.py", line 91, in collapse_excgroups
raise exc
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 128, in receive_or_disconnect
message = await wrap(wrapped_receive)
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 123, in wrap
result = await func()
File "<path>/venv310/lib/python3.10/site-packages/starlette/middleware/base.py", line 56, in wrapped_receive
raise RuntimeError(f"Unexpected message received: {msg['type']}")
RuntimeError: Unexpected message received: http.request
The error is coming from this line: https://github.com/encode/starlette/blob/master/starlette/middleware/base.py#L56
which appears to be starlette waiting for a client disconnect but instead getting the next request. (No idea why starlette wants the request to be closed instead of allowing it to be reused for the next request, but maybe there is something I am not aware of.)
I would (and will) ask about this in the starlette github, but I am posting here because I did not encounter this issue when running my FastAPI app with uvicorn, it only happens with nginx unit, so at a minimum, it appears that something is different here which is causing problems, and this is probably something that should be identified.
I was really happy when I discovered nginx unit; this issue is currently the only thing that is preventing me from adopting it.