For the sake of backwards compatibility, I'm running a complicated stack of apache (mod_wsgi) -> a2wsgi (ASGIMiddleware) -> fastapi, and with the update of fastapi==0.107.0 this broke, after they have internally switched to a relatively new version of Starlette (0.28.0).
In apache I'm getting the error RuntimeError: Unexpected message received: http.request, but this is here only to make this issue easier to find later.
I now tried to reduce this stack to make it easier to understand and think the a2wsgi part might be the issue or at least you may know what it actually is.
Based on the starlette hello-world i added a custom middleware and the a2wsgi.ASGIMiddleware. Removing the custom middle middleware fixes the issue (but removes the functionality).
from starlette.applications import Starlette
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware import Middleware
from starlette.responses import JSONResponse
from starlette.routing import Route
from a2wsgi import ASGIMiddleware
class HeaderAddTestMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
response.headers["X-Test"] = "Test"
return response
async def homepage(request):
return JSONResponse({"hello": "world"})
app = Starlette(
debug=True,
middleware=[
Middleware(HeaderAddTestMiddleware),
],
routes=[
Route("/", homepage),
],
)
application = ASGIMiddleware(app)
To run it i use uwsgi like this uwsgi --http :8000 --wsgi-file main.py.
Using starlette==0.27.0 and a2wsgi==1.10.0 this just works, but with starlette==0.28.0 and later (current version is starlette==0.37.0) i get this error on request.
❯ curl -v http://127.0.0.1:8000
* Trying 127.0.0.1:8000...
* Connected to 127.0.0.1 (127.0.0.1) port 8000
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 17
< content-type: application/json
< x-test: Test
<
* Connection #0 to host 127.0.0.1 left intact
{"hello":"world"}
[...]
[pid: 17764|app: 0|req: 28/28] 127.0.0.1 () {28 vars in 291 bytes} [Wed Feb 7 09:22:15 2024] GET / => generated 17 bytes in 5 msecs (HTTP/1.1 200) 2 headers in 71 bytes (1 switches on core 0)
Traceback (most recent call last):
File ".venv/lib/python3.12/site-packages/a2wsgi/asgi.py", line 235, in __call__
yield from self.error_response(start_response, message["exception"])
File ".venv/lib/python3.12/site-packages/a2wsgi/asgi.py", line 266, in error_response
start_response(
OSError: headers already sent
[pid: 17764|app: 0|req: 29/29] 127.0.0.1 () {28 vars in 291 bytes} [Wed Feb 7 09:22:17 2024] GET / => generated 17 bytes in 7 msecs (HTTP/1.1 200) 2 headers in 71 bytes (2 switches on core 0)
[...]
The hello-world response gets shipped anyway, and even the header is set as wanted. It also gives this error when i just return await call_next(request) in the dispatch method without actually modifying any header.
I would normally assume the issue is somewhere in BaseHTTPMiddleware, but running the same code using asgi via uvicorn (uvicorn main:app) it also works.
For the sake of backwards compatibility, I'm running a complicated stack of apache (mod_wsgi) -> a2wsgi (ASGIMiddleware) -> fastapi, and with the update of
fastapi==0.107.0this broke, after they have internally switched to a relatively new version of Starlette (0.28.0).In apache I'm getting the error
RuntimeError: Unexpected message received: http.request, but this is here only to make this issue easier to find later.I now tried to reduce this stack to make it easier to understand and think the a2wsgi part might be the issue or at least you may know what it actually is.
Based on the starlette hello-world i added a custom middleware and the
a2wsgi.ASGIMiddleware. Removing the custom middle middleware fixes the issue (but removes the functionality).To run it i use uwsgi like this
uwsgi --http :8000 --wsgi-file main.py.Using
starlette==0.27.0anda2wsgi==1.10.0this just works, but withstarlette==0.28.0and later (current version isstarlette==0.37.0) i get this error on request.The hello-world response gets shipped anyway, and even the header is set as wanted. It also gives this error when i just
return await call_next(request)in thedispatchmethod without actually modifying any header.I would normally assume the issue is somewhere in
BaseHTTPMiddleware, but running the same code using asgi via uvicorn (uvicorn main:app) it also works.