Starlette app hangs on Azure Functions when middleware based on BaseHTTPMiddleware is used
See original GitHub issueDescribe the bug
I am running a Starlette app through Azure Functions, using the ASGI support in Azure Functions to run the app. When I set up the app with no middlewares, it works fine. When I add the CORSMiddleware
it also works fine, but when I add any middleware which is a subclass of BaseHTTPMiddleware
, then all requests to the app hang and eventually timeout.
To reproduce
A simple reproducible example is available here. This defines a simple Starlette app as follows:
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.cors import CORSMiddleware
async def homepage(request):
return JSONResponse({"hello": "world"})
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
response.headers["Custom"] = "Example"
return response
app = Starlette(
debug=True,
routes=[
Route("/", homepage),
],
# Works with no middlewares defined
#
# Hangs with this line:
# middleware=[Middleware(CustomHeaderMiddleware)]
#
# Works with this line:
middleware = [Middleware(CORSMiddleware)]
)
This app is then deployed on Azure Functions, using their AsgiMiddleware
class, which interfaces between Azure Functions triggers and ASGI requests. The code is all available in the repo, but the key part is __init__.py
, which contains:
import azure.functions as func
from azure.functions import AsgiMiddleware
from .simple_app import app
def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
return AsgiMiddleware(app).handle(req, context)
Expected behavior
App works with all types of middleware
Actual behavior
As you can see from the comments at the bottom of the app, this works with no middlewares, or just the CORSMiddleware
, but hangs with the CustomHeaderMiddleware
which is derived from BaseHTTPMiddleware
.
Debugging material
As the app just hangs, there is no traceback to share.
Environment
- OS: Linux, on Azure Functions
- Python version: 3.9
- Starlette version: 0.16.0 (latest release at time of writing)
Additional context
This was first discovered in a FastAPI app called titiler - see https://github.com/developmentseed/titiler/issues/388. The author of that app realised it was only failing when using middleware which were a subclass of BaseHTTPMiddleware
, and suggested I try with raw Starlette and post an issue here.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:6 (5 by maintainers)
Top GitHub Comments
Looks like the easiest way to solve this is for
receive()
to return a disconnect if it has already been called once with the body. Functions doesn’t support streaming bodies, so it would never check for more body.@Kludex @robintw I’ll pick this up on the Microsoft/Azure Functions side and debug