Doesn't add etag when returning custom response
Closed this issue · 4 comments
I don't know what the solution here is, but in most cases I use TemplateResponse or JSONResponse, and in both cases no etags are added.
from typing import Any
from fastapi_etag import Etag, add_exception_handler
from fastapi import Depends, Request, FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
app = FastAPI()
add_exception_handler(app)
async def get_etag(request: Request) -> str:
return "myetag"
@app.get('/foobar', dependencies=[Depends(Etag(get_etag))])
async def repos(request: Request) -> Any:
return JSONResponse([])
client = TestClient(app)
r = client.get("/foobar")
print(r.headers)
I've solved this with a middleware for now:
def get_etag():
return "foo"
@app.middleware("http")
async def add_etags_everywhere(request: Request, call_next: Callable) -> Response:
etag = request.headers.get("if-none-match")
current_etag = get_etag()
if etag == current_etag:
return Response("", 304, headers={"etag": current_etag})
response: Response = await call_next(request)
if "etag" not in response.headers:
response.headers["etag"] = current_etag
return response
The problem is that returning a response object from the route completely overrides any changes to the response made in the dependency chain.
You could add the headers from response dependency to your new response like this, should work:
app.get('/foobar', dependencies=[Depends(Etag(get_etag))])
async def repos(request: Request, response: Response) -> Any:
return JSONResponse([], headers=response.headers)
But the middleware approach is probably better if you're adding etags the same way on every route
You could add the headers from response dependency to your new response like this, should work:
Thanks! I'll give that a try.
Feel free to close this (and maybe add this to the doc?, btw the examples in the docs don't work due to missing Depends usage and import)
But the middleware approach is probably better if you're adding etags the same way on every route
That sadly didn't work out because I hit fastapi/fastapi#1472
You could add the headers from response dependency to your new response like this, should work:
Thanks! I'll give that a try.
This worked nicely, thanks again