from __future__ import annotations from pathlib import Path from quart import Quart, Response, send_from_directory from repub.web.app import CACHE_BUSTED_STATIC_ASSETS, STATIC_DIR def register_static_routes(app: Quart) -> None: @app.get("/feeds/") async def published_feed(feed_path: str) -> Response: if not bool(app.config["REPUB_DEV_MODE"]): return Response(status=404) response = await send_from_directory( str(Path(app.config["REPUB_FEEDS_DIR"])), feed_path, ) if Path(feed_path).suffix == ".rss": response.mimetype = "application/rss+xml" return response @app.get("/admin/static/") async def admin_static_asset(filename: str) -> Response: return await _static_asset_response(filename) @app.get("/publisher/static/") async def publisher_static_asset(filename: str) -> Response: return await _static_asset_response(filename) async def _static_asset_response(filename: str) -> Response: logical_filename = _cache_busted_logical_filename(filename) if logical_filename is not None: response = await send_from_directory(str(STATIC_DIR), logical_filename) response.cache_control.public = True response.cache_control.max_age = 31536000 response.cache_control.immutable = True return response return await send_from_directory(str(STATIC_DIR), filename) def _cache_busted_logical_filename(filename: str) -> str | None: for logical_filename in CACHE_BUSTED_STATIC_ASSETS: logical_path = Path(logical_filename) prefix = f"{logical_path.stem}-" if filename.startswith(prefix) and filename.endswith(logical_path.suffix): return logical_filename return None