question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Starlette app hangs on Azure Functions when middleware based on BaseHTTPMiddleware is used

See original GitHub issue

Describe 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:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
tonybaloneycommented, Jan 11, 2022

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.

1reaction
tonybaloneycommented, Jan 11, 2022

@Kludex @robintw I’ll pick this up on the Microsoft/Azure Functions side and debug

Read more comments on GitHub >

github_iconTop Results From Across the Web

Function App breaks whenever one identity provider is ...
To keep it simple, I am using a Function App with two identity ... Users can either use our application if they authenticate...
Read more >
Why does fastapi hang when adding a middleware to print the ...
This hanging is basically because @app.middleware("http") based middlewares, are in back-end created by inheriting from Starlette's ...
Read more >
Exceptions - Starlette
The HTTPException class provides a base class that you can use for any handled exceptions. The ExceptionMiddleware implementation defaults to returning plain- ...
Read more >
Contrast Documentation - Contrast Security
assign different types of access, based on role, for each application ... If you are using Azure App Service or Docker you must...
Read more >
Microservice APIs MEAP V10
exposes, since there are many types of APIs that microservices can use to expose ... Starlette knows which function within your app to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found