cddb07a176
docs / deploy (push) Has been cancelled
docs / changes (push) Has been cancelled
docs / check-and-build (push) Has been cancelled
build container image / cpu (push) Has been cancelled
build container image / cuda (push) Has been cancelled
build container image / rocm (push) Has been cancelled
frontend checks / frontend-checks (push) Has been cancelled
frontend tests / frontend-tests (push) Has been cancelled
lfs checks / lfs-check (push) Has been cancelled
python checks / python-checks (push) Has been cancelled
python tests / py3.12: macos-default (push) Has been cancelled
python tests / py3.11: windows-cpu (push) Has been cancelled
python tests / py3.12: windows-cpu (push) Has been cancelled
python tests / py3.11: linux-cpu (push) Has been cancelled
typegen checks / typegen-checks (push) Has been cancelled
uv lock checks / uv-lock-checks (push) Has been cancelled
openapi checks / openapi-checks (push) Has been cancelled
python tests / py3.11: macos-default (push) Has been cancelled
python tests / py3.12: linux-cpu (push) Has been cancelled
51 lines
2.1 KiB
Python
51 lines
2.1 KiB
Python
from typing import Any
|
|
|
|
from starlette.exceptions import HTTPException
|
|
from starlette.responses import Response
|
|
from starlette.staticfiles import StaticFiles
|
|
from starlette.types import Scope
|
|
|
|
|
|
class NoCacheStaticFiles(StaticFiles):
|
|
"""
|
|
This class is used to override the default caching behavior of starlette for static files,
|
|
ensuring we *never* cache static files. It modifies the file response headers to strictly
|
|
never cache the files.
|
|
|
|
Static files include the javascript bundles, fonts, locales, and some images. Generated
|
|
images are not included, as they are served by a router.
|
|
|
|
This class also implements proper SPA (Single Page Application) routing by serving index.html
|
|
for any routes that don't match static files, enabling client-side routing to work correctly
|
|
in production builds.
|
|
"""
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any):
|
|
self.cachecontrol = "max-age=0, no-cache, no-store, , must-revalidate"
|
|
self.pragma = "no-cache"
|
|
self.expires = "0"
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def file_response(self, *args: Any, **kwargs: Any) -> Response:
|
|
resp = super().file_response(*args, **kwargs)
|
|
resp.headers.setdefault("Cache-Control", self.cachecontrol)
|
|
resp.headers.setdefault("Pragma", self.pragma)
|
|
resp.headers.setdefault("Expires", self.expires)
|
|
return resp
|
|
|
|
async def get_response(self, path: str, scope: Scope) -> Response:
|
|
"""
|
|
Override get_response to implement SPA routing.
|
|
|
|
When a file is not found and html mode is enabled, serve index.html instead of raising a 404.
|
|
This allows client-side routing to work correctly in SPAs.
|
|
"""
|
|
try:
|
|
return await super().get_response(path, scope)
|
|
except HTTPException as exc:
|
|
# If the file is not found (404) and html mode is enabled, serve index.html
|
|
# This allows client-side routing to handle the path
|
|
if exc.status_code == 404 and self.html:
|
|
return await super().get_response("index.html", scope)
|
|
raise
|