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.

Background tasks don't work with middleware that subclasses `BaseHTTPMiddleware`

See original GitHub issue

When using background tasks with middleware, requests are not processed until the background task has finished.

  1. Use the example below
  2. Make several requests in a row - works as expected
  3. Uncomment app.add_middleware(TransparentMiddleware) and re-run
  4. Make several requests in a row - subsequent ones are not processed until the 10 second sleep has finished (the first request returns before then though).

The same behaviour occurs with asyncio.sleep (async) and time.sleep (sync, run in threadpool)

import asyncio
import uvicorn
from starlette.applications import Starlette
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.background import BackgroundTask
from starlette.responses import JSONResponse


class TransparentMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        # simple middleware that does absolutely nothing
        response = await call_next(request)
        return response


app = Starlette(debug=True)
# uncomment to break
# app.add_middleware(TransparentMiddleware)


@app.route("/")
async def test(_):
    task = BackgroundTask(asyncio.sleep, 10)
    return JSONResponse("hello", background=task)


if __name__ == '__main__':
    uvicorn.run(app)

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:43
  • Comments:42 (17 by maintainers)

github_iconTop GitHub Comments

21reactions
sarangsbabu367commented, Oct 1, 2020

Any updates on this issue ?

12reactions
erewokcommented, Aug 12, 2020

Hi all, I had a PR to fix this behavior (#1017 ) but it relied on forcing the response to remain unevaluated, which further confused those users who were relying on having a fully-evaluated response inside their middleware functions (#1022 ). In other words, there are contradictory goals here.

After looking at this BaseHTTPMiddleware class over the last week, I have come to the following conclusions:

  • We should discourage the use of BaseHTTPMiddleware in favor of raw ASGI middleware which includes a method def __call__(self, scope, receive, send):, and

  • If people still want to use this middleware class, it should never be used with StreamingResponse/FileResponse endpoints.

Unfortunately, while the BaseHTTPMiddleware class offers an easier interface because it provides a request argument and promises something like a response, this middleware class also encourages users to think about the asgi app functionality in a “complete” or “finished” way. This means this class will either load the entirety of streaming requests into memory (#1012 ) and run the background before returning the response (this issue), or if we fix those problems, that it will then encourage users to leave resources in a pending or open state, an arguably worse result. In short, it’s problematic.

Again, these problems should be absent if you avoid subclassing BaseHTTPMiddleware.

Lastly, I think it’s worth leaving this issue open so that other users who have the same problem can see it and see that it remains an open issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Background tasks don't work with middleware that subclasses ...
When using background tasks with middleware, requests are not processed until the background task has finished. Use the example below ...
Read more >
How to use background tasks with Starlette when there's no ...
Solved! Starlette Middleware: class BackgroundTaskMiddleware(BaseHTTPMiddleware): async def dispatch( self, request: Request, ...
Read more >
Middleware - Starlette
An abstract class that allows you to write ASGI middleware against a request/response interface. Usage. To implement a middleware class using BaseHTTPMiddleware ......
Read more >
Starlette Quick Manual - 0xBF
The above TemplateResponse and JSONResponse are subclass of the Response ... from starlette.background import BackgroundTasks async def ...
Read more >
Middleware - FastAPI
If you have dependencies with yield , the exit code will run after the middleware. If there were any background tasks (documented later),...
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

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