-
First Check
Commit to Help
Example Codefrom typing import Annotated
import fastapi
def custom_request(request: fastapi.Request) -> fastapi.Request:
return request
app = fastapi.FastAPI()
@app.get("/bad/endpoint")
def test_endpoint(request: Annotated[fastapi.Request, fastapi.Depends(custom_request)]):
return {"status": "this doesn't work"}DescriptionSummaryPrior to the changes merged in #4871, it was possible to create a FastAPI dependency that returned an object of type There are a variety of workarounds, including using the old style non- Here's the error that you get when running the above app: Why Do I Need This?The contrived example above seems silly, and it is, but it's the smallest thing I could do to illustrate the problem we see. Our application has a custom authentication and authorization layer, and we've built it by leveraging FastAPI dependencies. In order to ensure that we've run authentication and authorization for every endpoint in our application, we have a wrapper that's applied to all path operations via a custom route class. It behaves like so (below is a dumbed down version): import inspect
import fastapi
import makefun
class SecureRoute(fastapi.routing.APIRoute):
def __init__(self, path, endpoint, **kwargs):
async def wrapper(
*args,
my_request: Annotated[fastapi.Request, fastapi.Depends(_get_my_request)],
**kwargs,
):
_do_security_stuff(my_request)
return await endpoint(*args, **kwargs)
my_request_arg = inspect.Parameter(
name="ny_request",
kind=inspect.Parameter.KEYWORD_ONLY,
annotation=Annotated[fastapi.Request, fastapi.Depends(_get_my_request)],
)
wrapped_endpoint = makefun.create_wrapper(endpoint, wrapper, append_args=my_request_arg)
super().__init__(path=path, endpoint=wrapped_endpoint, **kwargs)
self.endpoint = endpoint
def _get_my_request(request: fastapi.Request) -> fastapi.Request:
# `_get_my_request` is to be used in the context of a `fastapi.Depends()` call
# to get access to the `fastapi.Request` object inside of our wrapper handler without
# directly specifying a keyword parameter of type `fastapi.Request`. FastAPI's dependency
# system special-cases arguments of type `fastapi.Request` and only allows one per
# endpoint. by specifying the `fastapi.Request` argument in a sub-dependency, we're
# able to access this named argument from within our wrapper function without overriding
# the actual endpoint's naming of `fastapi.Request`, when needed.
return requestOperating SystemLinux, macOS Operating System DetailsNo response FastAPI Version0.95.1 Python VersionPython 3.9.1 Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
@nzig I've seen in the other discussions that you've been great in responding to issues that are related to #4871, so if you're able to find the time it would be great if you could provide any context on the |
Beta Was this translation helpful? Give feedback.
Thanks for tagging me.
Why this is an error
The reason is that an annotation like
Annotated[fastapi.Request, fastapi.Depends(custom_request)]is ambiguous. There are two conflicting behaviors here:Request, FastAPI will inject the request objectDepends, FastAPI will resolve the dependency and inject that.Prior to #4871, FastAPI would arbitrarily choose one over the other, but this was not documented. That PR changed it to an error if the annotation would be ambiguous.
How to avoid the error
In your case, it does indeed seem that you create a dependency that returns a
Request, so it's hard to avoid the ambiguity. However, I think y…