fastapi-cache icon indicating copy to clipboard operation
fastapi-cache copied to clipboard

@cache decorator is not behaving properly in swagger. Giving same etag and same respones for different header with same query param

Open Debapriya-kvelld opened this issue 5 months ago • 0 comments

Check out this simple code snippet -

from fastapi import FastAPI, Header
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from fastapi_cache.backends.inmemory import InMemoryBackend

app = FastAPI()


@app.on_event("startup")
async def startup():
    FastAPICache.init(InMemoryBackend(), prefix="fastapi-cache")


def get_dummy_data(id: int, header: str):
    return {"message": f"This is a response from the server with id {id} and header {header}"}


@app.get("/hello/{id}")
@cache(expire=60)
async def hello(id: int, header: str = Header(default="")):
    print(f"id: {id}, header: {header}")
    return get_dummy_data(id, header)

These are the responses I got using curl from the above code which is fine:

$curl -X GET "http://localhost:8000/hello/123" -H "header: 1" -v
Note: Unnecessary use of -X or --request, GET is already inferred.
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8000...
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000
* using HTTP/1.x
> GET /hello/123 HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.12.1
> Accept: */*
> header: 1
> 
< HTTP/1.1 200 OK
< date: Mon, 26 May 2025 14:56:17 GMT
< server: uvicorn
< content-length: 73
< content-type: application/json
< cache-control: max-age=60
< etag: W/8202067273124472754
< x-fastapi-cache: MISS
< 
{"message":"This is a response from the server with id 123 and header 1"}* Connection #0 to host localhost left intact
$curl -X GET "http://localhost:8000/hello/123" -H "header: 2" -v
Note: Unnecessary use of -X or --request, GET is already inferred.
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8000...
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000
* using HTTP/1.x
> GET /hello/123 HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.12.1
> Accept: */*
> header: 2
>
< HTTP/1.1 200 OK
< date: Mon, 26 May 2025 14:56:26 GMT
< server: uvicorn
< content-length: 73
< content-type: application/json
< cache-control: max-age=60
< etag: W/-6078313225852588722
< x-fastapi-cache: MISS
<
{"message":"This is a response from the server with id 123 and header 2"}* Connection #0 to host localhost left intact
$curl -X GET "http://localhost:8000/hello/123" -H "header: 1" -v
Note: Unnecessary use of -X or --request, GET is already inferred.
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8000...
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000
* using HTTP/1.x
> GET /hello/123 HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.12.1
> Accept: */*
> header: 1
>
< HTTP/1.1 200 OK
< date: Mon, 26 May 2025 14:56:29 GMT
< server: uvicorn
< content-length: 73
< content-type: application/json
< cache-control: max-age=47
< etag: W/8202067273124472754
< x-fastapi-cache: HIT
<
{"message":"This is a response from the server with id 123 and header 1"}* Connection #0 to host localhost left intact
$curl -X GET "http://localhost:8000/hello/123" -H "header: 2" -v
Note: Unnecessary use of -X or --request, GET is already inferred.
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8000...
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000
* using HTTP/1.x
> GET /hello/123 HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.12.1
> Accept: */*
> header: 2
>
< HTTP/1.1 200 OK
< date: Mon, 26 May 2025 14:56:32 GMT
< server: uvicorn
< content-length: 73
< content-type: application/json
< cache-control: max-age=54
< etag: W/-6078313225852588722
< x-fastapi-cache: HIT
<
{"message":"This is a response from the server with id 123 and header 2"}* Connection #0 to host localhost left intact

But the same thing in swagger works differently. The header is somehow not getting considered for caching.

Once I execute it for id=1 and header=1 it generates an etag which stays the same for id=1 and header=2: Image

Like this: Image

Only if I change the query parameter, then the response changes:

Image

Please provide some solution for this.

PS: I have already tried custom key builder approach.

Debapriya-kvelld avatar May 26 '25 15:05 Debapriya-kvelld