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.

Middleware Request parse Hangs forever

See original GitHub issue

I’m currently trying to integrate some metrics tooling in a middleware where I need to inspect the request body. The problem I am seeing is that this triggers the request to hang forever. The following is how you can reproduce it.

app = Starlette()
class ParseRequestMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next: RequestResponseEndpoint):
        # payload = await request.json()  # This will cause test() to hang
        response = await call_next(request)
        payload = await request.json()  # Hangs forever
        return response


async def test(scope: Scope, receive: Receive, send: Send):
    request = Request(scope=scope, receive=receive)
    data = await request.json()
    response = Response(status_code=405)
    await response(scope, receive, send)


app.mount("/test", test)
app.add_middleware(ParseRequestMiddleware)

I’m still pretty new to starlette but it seems to be an issue with the fact that the middleware and ASGI app use different Request objects and therefore can’t share the Request._body cache. Which means they exhaust the stream on the first read and the second read isn’t correctly detecting that the stream is exhausted and so gets stuck in that while True loop. I’m not sure I haven’t dove deeper than the Request object. I’m not sure where the code is for the receive function that gets passed into the ASGI App is.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:13
  • Comments:15 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
nikordariscommented, Feb 27, 2020

So i confirmed that if I use the same Request object it works. I added a middleware to store the request object into a ContextVar and if I use that instead of the receive and send passed into the ASGI app then the request doesn’t hang anymore. This might be enough of a workaround for me right now but the more apps I add (especially third party ones) the more of a problem this will become.

Update: Running more tests today I had hoped to reduce the number of places I have to ignore the send/receive args but it looks like BaseHTTPMiddleware also creates a new Request object. So basically anyone who needs to share the request body data should get the request object from ContextVars to ensure the stream is only read once and doesn’t get exhausted.

I’m still unclear whether this is all by design and the developer is expected to manage a cache of the data streams. It seems like at minimum it shouldn’t hang and it should be raising an error instead of getting stuck in an infinite loop. I would greatly appreciate some insights here whenever you have a moment @tomchristie

1reaction
loikkicommented, Mar 18, 2022

If someone is experiencing the same issue and cannot wait until a solution is found, my current simple fix is simply to patch the Request. For example (the code is not tested, but you can see the idea):

app = Starlette()
class ParseRequestMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next: RequestResponseEndpoint):
        payload = await request.json()  # This will cause test() to hang
        with patch.object(Request, "body", request.body):
            response = await call_next(request)
            payload = await request.json()  # Hangs forever
            return response


async def test(scope: Scope, receive: Receive, send: Send):
    request = Request(scope=scope, receive=receive)
    data = await request.json()
    response = Response(status_code=405)
    await response(scope, receive, send)


app.mount("/test", test)
app.add_middleware(ParseRequestMiddleware)
Read more comments on GitHub >

github_iconTop Results From Across the Web

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 >
Node server hangs up when calling a request multiple times.
So I am making a login form for my website and when calling the /submitlogin post request it hangs up after few times...
Read more >
body-parser | Yarn - Package Manager
Parse incoming request bodies in a middleware before your handlers, available under the req.body property. Note As req.body 's shape is based on...
Read more >
Top 10 Mistakes Node.js Developers Make - AirPair
forever. What these modules do is to watch for file changes and restart the server for you. Let us take nodemon for example....
Read more >
Common API mistakes and how to avoid them - LogRocket Blog
When we request data from an upstream service and convert it into an ... However, we are forever stuck with both a hometown_name...
Read more >

github_iconTop Related Medium Post

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