Is there a way to pass an argument to a function defined within the dependencies
argument of, for instance, app.get
? If there isn't, what other options exist ?
I can do the following to test a request, including examining the bearer token, before it reaches the endpoint handler:
async def verify_token(Authorization: Annotated[str, Header()]):
# decode token and do processing based on it
@app.get("/read_items/", dependencies=[Depends(verify_token)])
async def read_items():
return [{"item": "Foo"}, {"item": "Bar"}]
but what I really want to do is provide an argument to verify_token
, like this:
@app.get("/read_items/", dependencies=[Depends(verify_token("red")])
async def read_items():
return [{"item": "Foo"}, {"item": "Bar"}]
in this scenario verify_token
would accept a string as an argument and the value of that string would be easily seen by anyone inspecting the code.
Of course this type of outcome could be produced by using a decorator:
@verify_token_decorator("red")
@app.get("/read_items/")
async def read_items():
return [{"item": "Foo"}, {"item": "Bar"}]
but decorators cannot inspect the contents of Request headers and so such a decorator would not be able to inspect the token.
Is there a way to do the functional equivalent of passing a value into a function within the dependencies
argument of an end point?
The parameter to Depends()
can be any Python callable. The FastAPI Advanced Dependencies guide has a couple examples, specifically oriented around classes. But in your example, so long as verify_token("red")
returns a callable with the right syntax and type annotations, FastAPI can use it as a dependency.
The easy way is to have the function return another function:
def verify_token(color: str) -> Callable[[str], None]:
async def verifier(Authorization: Annotated[str, Header()]):
...
return verifier
@app.get("/read_items/", dependencies=[Depends(verify_token("red"))])
async def read_items():
...
The class-based approach shown in the documentation would work too. Any (fixed) parameters you pass inside the Depends()
would be passed to the __init__
constructor, and any runtime parameters would be passed to __call__
.
class TokenVerifier:
def __init__(self, color: str):
self.color = color
def __call__(self, Authorization: Annotated[str, Header()]):
...
@app.get("/read_items/", dependencies=[Depends(TokenVerifier("red"))])
async def read_items():
...