supertokens-python icon indicating copy to clipboard operation
supertokens-python copied to clipboard

supertokens FastAPI middleware uses BaseHTTPMiddleware which breaks async/background tasks

Open atambo opened this issue 2 years ago • 7 comments

See the starlette issue as well as the limitations section of the documentation.

It seems like using BaseHTTPMiddleware breaks some things with async/background tasks in FastAPI and people generally recommend switching your middleware to be pure ASGI middleware for maximum compatibility.

Unfortunately, I've been noticing this issue ever since I integrated the supertokens middleware into my application.

atambo avatar Jun 10 '23 01:06 atambo

Thanks for opening this issue @atambo . We will have a look at this in the coming week.

rishabhpoddar avatar Jun 10 '23 05:06 rishabhpoddar

Seems like starlette was thinking about deprecating BaseHTTPMiddleware but ended up backing off from doing so: https://github.com/encode/starlette/pull/1898

However, it still seems like the recommended approach is to use a pure ASGI middleware.

atambo avatar Jun 12 '23 14:06 atambo

Hi @atambo, Thanks for pointing this out. I quickly tried to replace BaseHTTPMiddleware. But it was getting slightly complicated. Starlette is on a lower level and the objects don't seem easily convertable into each other (esp. Message <-> Response). So we will take a look at this when at a later point in time.

Keeping this issue open since it's valid. We will try to get resolve this as soon as we have time. In the meantime, I can help you with finding a workaround for your use case if you provide more details :)

KShivendu avatar Jun 13 '23 07:06 KShivendu

Hi, this is causing issues for me currently, I'd like to run an async function in a BackgroundTask but having the SuperTokens middleware is blocking my main event loop. I need something like the following:

import asyncio
from fastapi import BackgroundTasks, FastAPI
from fastapi import FastAPI
from supertokens_python import init, InputAppInfo, SupertokensConfig
from supertokens_python.framework.fastapi import get_middleware
from supertokens_python.recipe import dashboard, emailpassword, session, userroles


app = FastAPI()

app.add_middleware(get_middleware())

init(
    app_info=InputAppInfo(
        app_name="name",
        api_domain="localhost",
        website_domain="localhost",
        api_base_path="/auth",
        website_base_path="/auth",
    ),
    supertokens_config=SupertokensConfig(
        connection_uri= "uri",
        api_key= "key",
    ),
    framework="fastapi",
    recipe_list=[
        session.init(),
        userroles.init(),
        dashboard.init(),
        emailpassword.init(),
    ],
    mode="asgi",
)

@app.get("/")
async def root():
    return {"message": "Hello World"}

async def simple_task():
    await asyncio.sleep(10)
    print("completed")

@app.post("/test")
async def test(background_tasks: BackgroundTasks):
    background_tasks.add_task(simple_task)
    return {"message": "Task started"}

AngusParsonson avatar Aug 01 '23 23:08 AngusParsonson

@AngusParsonson I tried your code, it seems to be working for me and is able to run the async tasks. What's the error that your're seeing on your machine?

KShivendu avatar Aug 02 '23 06:08 KShivendu

Hi @KShivendu, thanks for the response.

There is no error, it is just that the main event loop is blocked whilst the task is running. If you try to hit a simple get endpoint whilst the background task is running, then it will not complete until the background task is finished.

This is an issue with starlette, the way I got around it was by using asyncio.create_task() instead of the background task.

AngusParsonson avatar Aug 07 '23 18:08 AngusParsonson

Ahh yes. I'll try to dive into this and find a clean solution sometime soon.

Good to know that you already found a workaround in the meantime. I believe it's sufficient to solve your problem for now?

KShivendu avatar Aug 08 '23 06:08 KShivendu