class User(BaseModel):
name: str
token: str
fake_db = [
User(name='foo', token='a1'),
User(name='bar', token='a2')
]
async def get_user_by_token(token: str = Header()):
for user in fake_db:
if user.token == token:
return user
else:
raise HTTPException(status_code=401, detail='Invalid token')
@router.get(path='/test_a', summary='Test route A')
async def test_route_a(user: User = Depends(get_user_by_token)):
return {'name': user.name}
@router.get(path='/test_b', summary='Test route B')
async def test_route_a(user: User = Depends(get_user_by_token)):
return {'name': user.name}
I would like to avoid code duplication. Is it possible to somehow set the line user: User = Depends(get_user_by_token)
for the entire router? At the same time, I need the user
object to be available in each method.
It is very important that the openapi says that you need to specify a header with a token for the method.
You can use the dependencies
parameter to add global dependencies when creating the router
instance:
router = APIRouter(dependencies=[Depends(get_user_by_token)])
or, when adding the router
to the app
instance:
app.include_router(router, dependencies=[Depends(get_user_by_token)])
Please have a look at FastAPI's documentation on Dependencies for more details.
As for getting the return value of a global dependency, you can't really do that. The way around this issue is to store the returned value to request.state
(as described here), which is used to store arbitrary state (see the implementation of State
as well). Hence, you could have something like this:
def get_user_by_token(request: Request, token: str = Header()):
for user in fake_db:
if user.token == token:
request.state.user = user
# ...
Then, inside your endpoint, you could retrieve the user object using request.state.user
, as described in this answer.