Files
NODEDC_MISSION_CORE/src/k1link/web/frontend_assets.py
T
DCCONSTRUCTIONS 0ca7316a24 wip(k1): checkpoint connection recovery rewrite
Capture the current unreleased K1 connection, recovery, lifecycle, viewer, and test work as a single known-bad baseline for subsequent fixes.
2026-08-14 14:57:50 +03:00

50 lines
1.6 KiB
Python

from __future__ import annotations
import re
from pathlib import Path
from fastapi.staticfiles import StaticFiles
from starlette.responses import Response
from starlette.types import Scope
HTML_NO_STORE = "no-store"
HASHED_ASSET_IMMUTABLE = "public, max-age=31536000, immutable"
_MODULE_SCRIPT = re.compile(
r'<script\b[^>]*\bsrc=["\'](?P<src>/assets/[^"\']+)["\'][^>]*>',
re.IGNORECASE,
)
_HASHED_ASSET = re.compile(
r"^assets/(?:.+)-[A-Za-z0-9_-]{8,}\.[A-Za-z0-9]+$",
)
def frontend_build_id(frontend_root: Path) -> str | None:
"""Return the exact content-hashed module loaded by the current index."""
try:
index = (frontend_root / "index.html").read_text(encoding="utf-8")
except OSError:
return None
for match in _MODULE_SCRIPT.finditer(index):
source = match.group("src")
if _HASHED_ASSET.fullmatch(source.removeprefix("/")):
return source
return None
class ControlStationStaticFiles(StaticFiles):
"""Serve the SPA shell fresh while retaining immutable hashed assets."""
async def get_response(self, path: str, scope: Scope) -> Response:
response = await super().get_response(path, scope)
if response.status_code >= 400:
return response
content_type = response.headers.get("content-type", "").lower()
normalized = path.lstrip("/")
if content_type.startswith("text/html"):
response.headers["Cache-Control"] = HTML_NO_STORE
elif _HASHED_ASSET.fullmatch(normalized):
response.headers["Cache-Control"] = HASHED_ASSET_IMMUTABLE
return response