fastapi-cache
fastapi-cache copied to clipboard
Error when using FastAPI request state variable AND also body parameter
I have a FastAPI POST endpoint which receives a parameter in the request body. A global FastAPI Depends sets a Request state value which I want to retrieve in my method.
The following works fine:
from pydantic import BaseModel
from fastapi import APIRouter, Request
class MyPydanticValue(BaseModel):
# some properties here
router = APIRouter()
@router.post(
"/foo"
)
def perform_action(
my_val: MyPydanticValue
request: Request
):
# do something with my_val
...
# and also reference a state value that was set globally elsewhere
print(request.state.x_some_value)
FastAPI sees the my_val parameter, recognises that it is a Pedantic model and therefore parses it from the request body.
I now want to cache the function, so I use @cache:
@router.post(
"/foo"
)
@cache(expire=300)
def perform_action(
my_val: MyPydanticValue
request: Request
):
# do something with my_val
...
#and also reference a state value that was set globally elsewhere
print(request.state.x_some_value)
Now I get an exception:
TypeError: perform_action() got multiple values for argument 'my_val'
The fastapi-cache documentation states:
The cache decorator injects dependencies for the Request and Response objects, so that it can add cache control headers to the outgoing response, and return a 304 Not Modified response when the incoming request has a matching If-Non-Match header. This only happens if the decorated endpoint doesn't already list these dependencies already.
My reading of that is that the injection shouldn't happen because I declare a parameter referring to the Request already. I think that's what is happening in the source code for the @cache decorator: https://github.com/long2ice/fastapi-cache/blob/v0.2.1/fastapi_cache/decorator.py#L41-L46. However, I think that my function is indeed actually getting a request parameter being injected by fastapi-cache and then subsequently by FastAPI. Alternatively, something that the cache wrapper is doing is messing up the parsing of the body.
What am I doing wrong - is this a bug? If so, is there a way of working around this? How do I access the state value in the endpoint function whilst also parsing the Pydantic model from the request body?
You can try install main.
pip install git+https://github.com/long2ice/fastapi-cache.git
But if the post method you use will not cache, if you want to test, you can modify it to return false. https://github.com/long2ice/fastapi-cache/blob/8945ac7a3a7d1533388a81460afdc2b5f0b1dfc2/fastapi_cache/decorator.py#L82-L83
I've traced the error to this line: https://github.com/long2ice/fastapi-cache/blob/v0.2.1/fastapi_cache/decorator.py#L152
return await ensure_async_func(request, *args, **kwargs)
Is there a reason why this particular invocation of the function adds a request argument, whereas this does not happen anywhere else in the code? I don't think that request argument belongs in that call. It results in too many arguments being passed to the underlying function.
@john-tipper Did you ever find a workaround for this? Running into the same thing.
Same thing, can someone answer?
hi any update? can we please open a PR and fix the relevant line?
I also have the same issue
Try changing your method to GET instead of POST. It worked for me.