Home > Software design >  Override global dependency for certain endpoints in FastAPI
Override global dependency for certain endpoints in FastAPI

Time:07-28

I have a FastAPI server that communicates with a web app. My web app also has 2 types of users, Users (non-admins) and Admins. I added a global dependency to FastAPI to verify the user. I want the verify dependency to only allow Admins to access endpoints by default, and have some decorator (or something similar) to allow non-admins to access certain routes. This way, no one accidentally creates a public route that is supposed to be only for admins.


    def verify_token(request: Request):
      # make sure the user's auth token is valid
      # retrieve the user's details from the database
      # make sure user is Admin, otherwise throw HTTP exception
      return True
      
    app = FastAPI(
            title="My App",
            dependencies=[Depends(verify_token)]
          )
          
    @app.get(/admins_only)
    def admins_only():
      # this works well!
      return {'result': 2}
      
    @app.get(/non_admin_route)
    def non_admin_route():
      # this doesn't work because verify_token
      # only allows admins by default, but it should
      # be accessible to non admins
      return {'result': 1}

CodePudding user response:

You cannot have conditional global dependencies. You either have them on all endpoints of your app, or on none of them. My recommendation is to split your endpoints in two routers, and only add routes to the respective routers. Then you can add a global dependency to only one of the routers like this:

from fastapi import APIRouter, FastAPI, Request, Depends

def verify_token(request: Request):
      # make sure the user's auth token is valid
      # retrieve the user's details from the database
      # make sure user is Admin, otherwise throw HTTP exception
      return True
      
app = FastAPI(
        title="My App",
        )
        
only_admin_router = APIRouter(
    tags=["forAdmins"],
    dependencies=[Depends(verify_token)]
)

all_users_router = APIRouter(tags="forEverybody")

@only_admin_router.get("/admins_only")
def admins_only():
    # this will only work if verify doesn't raise.
    return {'result': 2}
    
@all_users_router.get("/non_admin_route")
def non_admin_route():
    #this will work for all users, verify will not be called.
    return {'result': 1}

app.include_router(only_admin_router)
app.include_router(all_users_router)
  • Related