Spaces:
Running
Running
fix(static): serve shared brand assets with CSS MIME
#9
by betterwithage - opened
- serve.py +11 -0
- tests/test_static_brand_assets.py +33 -0
serve.py
CHANGED
|
@@ -1800,6 +1800,17 @@ def _lambda_aggregate(axes: list[float]) -> float:
|
|
| 1800 |
if ASSETS_DIR.exists():
|
| 1801 |
app.mount("/assets", StaticFiles(directory=str(ASSETS_DIR)), name="assets")
|
| 1802 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1803 |
|
| 1804 |
# ---------------------------------------------------------------------------
|
| 1805 |
# Health
|
|
|
|
| 1800 |
if ASSETS_DIR.exists():
|
| 1801 |
app.mount("/assets", StaticFiles(directory=str(ASSETS_DIR)), name="assets")
|
| 1802 |
|
| 1803 |
+
# The shared brand injector deliberately uses absolute ``/static/...`` URLs so
|
| 1804 |
+
# every HTML surface (including nested ``/elite/*`` pages) resolves the same
|
| 1805 |
+
# zero-CDN assets. The SPA catch-all maps a request path underneath STATIC_DIR;
|
| 1806 |
+
# without this mount, ``/static/brand-tokens.css`` becomes
|
| 1807 |
+
# ``STATIC_DIR/static/brand-tokens.css`` and falls through to HTML. Browsers
|
| 1808 |
+
# then reject the response under strict MIME checking. Mount the already-
|
| 1809 |
+
# packaged public tree before the catch-all so CSS, fonts and other explicitly
|
| 1810 |
+
# referenced static assets retain their real media types.
|
| 1811 |
+
if STATIC_DIR.exists():
|
| 1812 |
+
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
|
| 1813 |
+
|
| 1814 |
|
| 1815 |
# ---------------------------------------------------------------------------
|
| 1816 |
# Health
|
tests/test_static_brand_assets.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
|
| 3 |
+
from fastapi import FastAPI
|
| 4 |
+
from fastapi.staticfiles import StaticFiles
|
| 5 |
+
from fastapi.testclient import TestClient
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 9 |
+
STATIC_DIR = ROOT / "static"
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def test_brand_assets_are_packaged_and_served_as_css():
|
| 13 |
+
app = FastAPI()
|
| 14 |
+
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
|
| 15 |
+
client = TestClient(app)
|
| 16 |
+
|
| 17 |
+
for name in ("brand-tokens.css", "brand-bridge.css"):
|
| 18 |
+
source = STATIC_DIR / name
|
| 19 |
+
assert source.is_file(), f"missing packaged brand asset: {name}"
|
| 20 |
+
|
| 21 |
+
response = client.get(f"/static/{name}")
|
| 22 |
+
assert response.status_code == 200
|
| 23 |
+
assert response.headers["content-type"].startswith("text/css")
|
| 24 |
+
assert response.content == source.read_bytes()
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def test_static_mount_precedes_the_spa_catch_all():
|
| 28 |
+
source = (ROOT / "serve.py").read_text(encoding="utf-8")
|
| 29 |
+
mount = 'app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")'
|
| 30 |
+
catch_all = '@app.get("/{full_path:path}")'
|
| 31 |
+
|
| 32 |
+
assert source.count(mount) == 1
|
| 33 |
+
assert source.index(mount) < source.index(catch_all)
|