Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use middleware for a specific route only in a single APIRouter #4437

Closed
6 of 9 tasks
ahnaf-zamil opened this issue Jan 17, 2022 · 2 comments
Closed
6 of 9 tasks
Labels
question Question or problem question-migrate

Comments

@ahnaf-zamil
Copy link

ahnaf-zamil commented Jan 17, 2022

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

async def auth_required_middleware(request: Request, call_next: Coroutine):
    """Middleware for authenticating users on required routes"""
    token = str(
        request.cookies.get("token")
    )  # Stringyfy-ing because pyjwt might cry if it gets NoneType

    try:
        user_id = JWTService.verify_and_return_id(token)
        request.state.user_id = user_id
        response: StreamingResponse = await call_next(request)
        return response
    except:
        return JSONResponse(content={"description": "Unauthorized"}, status_code=401)

Description

FastAPI has a feature to have sub-apps. But it's not applicable in all cases, especially in my case where I have an APIRouter instance with 3 path operations/routes: login_user, create_user, get_logged_in_user. And I have an authentication middlware.

I spent a lot of time trying to find a way to only use that middleware in the get_logged_in_user operation, and not the other ones. But I found nothing regarding this. All I found online was using sub-apps, but I was trying to find a way to be able to use middlewares for a few specific routes in the same APIRouter instance.

So is there some kind of way where I can attach a middleware to a select few routes/operations in a single APIRouter instance? Because at the moment, the middleware is being triggered on all routes, including my user create and login path operations; which isn't practical.

This is how I'm adding my middleware, since it's in a separate file.

app.middleware("http")(
    auth_required_middleware
)  # Using decorators the way they were not meant to be ig

Operating System

Linux

Operating System Details

Linux Mint. Kernel version: 5.4.0-74-generic

DE: Not using one, just DWM

FastAPI Version

0.72.0

Python Version

Python 3.8.10

Additional Context

I have just taken a look at the source code, and it seems that the FastAPI middleware system is actually handled by Starlette. So
does that mean per-route/per-APIRouter middleware is something unrelated to FastAPI but related to Starlette itself?

@ahnaf-zamil ahnaf-zamil added the question Question or problem label Jan 17, 2022
@STeveShary
Copy link

@ahnaf-zamil Rather than think about this as a middleware, you could add in a single line a reusable function to get the logged in user. An example to look at would be here: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/

Another pattern using the middleware is to define a list of "unauthenticated" endpoints. And you only have the middleware apply the user checking if the path does not match any of the unauthenticated endpoints.

@ahnaf-zamil
Copy link
Author

Ah thanks a lot! I will be closing this issue then

@tiangolo tiangolo changed the title [Question] How to use middleware for a specific route only in a single APIRouter How to use middleware for a specific route only in a single APIRouter Feb 24, 2023
@tiangolo tiangolo reopened this Feb 27, 2023
Repository owner locked and limited conversation to collaborators Feb 27, 2023
@tiangolo tiangolo converted this issue into discussion #6494 Feb 27, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests

3 participants