Coverage for src/kwai/frontend/etag_file_response.py: 96%
24 statements
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
1from starlette._compat import md5_hexdigest # noqa
2from pathlib import Path
4from fastapi import Request
5from fastapi.responses import FileResponse, Response
8class EtagFileResponse(FileResponse):
9 """A FileResponse that will check the etag when if-none-match header is passed.
11 _generate_etag uses the same implementation as FileResponse.
12 FileResponse automatically sets the etag header with this etag value.
13 """
15 def __init__(self, path: Path, **kwargs) -> None:
16 super().__init__(path, **kwargs)
17 self._path = path
19 def _generate_etag(self) -> str:
20 file_stat = self._path.stat()
21 etag_base = str(file_stat.st_mtime) + "-" + str(file_stat.st_size)
22 return f'"{md5_hexdigest(etag_base.encode(), usedforsecurity=False)}"'
24 async def __call__(self, scope, receive, send) -> None:
25 """Check the etag, and return 304 when the file is not modified."""
26 request = Request(scope, receive)
27 if_none_match = request.headers.get("if-none-match")
29 if not if_none_match:
30 await super().__call__(scope, receive, send)
31 return
33 etag = self._generate_etag()
34 if if_none_match == etag:
35 response = Response(status_code=304)
36 await response(scope, receive, send)
37 return
39 await super().__call__(scope, receive, send)