spb/hfmarketdata
Public
Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)
JavaScript 53.7%
Python 38.3%
CSS 4.6%
TypeScript 3.1%
1"""SPA fallback (core/spa.py) on a bare FastAPI app with a fake Vite dist: known routes → 200 shell, unknown → 404 shell,2real files served, hashed assets immutable + gzipped, API paths never answered by the shell."""3from __future__ import annotations45import pytest6from fastapi import FastAPI7from fastapi.testclient import TestClient8from starlette.middleware.gzip import GZipMiddleware91011@pytest.fixture(scope="module")12def spa_client(tmp_path_factory, app):13 from core import errors, http, spa14 dist = tmp_path_factory.mktemp("dist")15 (dist / "index.html").write_text("<!doctype html><html><body><div id=root></div><script>/*shell*/</script></body></html>" + " " * 1500)16 (dist / "assets").mkdir()17 (dist / "assets" / "index-abc123.js").write_text("console.log('hfmd');" * 200)18 (dist / "favicon.svg").write_text("<svg xmlns='http://www.w3.org/2000/svg'></svg>")19 (dist / "docs").mkdir()20 (dist / "docs" / "index.html").write_text("<!doctype html><html><body>prerendered docs</body></html>")21 (dist / "limits.html").write_text("<!doctype html><html><body>prerendered limits</body></html>")22 a = FastAPI(openapi_url=None, docs_url=None, redoc_url=None)23 errors.install(a)24 a.add_middleware(GZipMiddleware, minimum_size=1024)2526 @a.get("/v1/ping")27 def ping():28 return {"ok": True}2930 @a.get("/health")31 def health():32 return {"status": "ok"}3334 http.install(a)35 assert spa.install(a, dist) is True36 with TestClient(a) as c:37 yield c383940def test_root_and_known_routes_serve_shell_200(spa_client):41 for path in ("/", "/playground", "/charts", "/signin", "/dashboard", "/dashboard/keys", "/admin/users", "/integrations/mcp", "/pricing"):42 r = spa_client.get(path)43 assert r.status_code == 200, path44 assert "text/html" in r.headers["content-type"] and "<div id=root>" in r.text45 assert r.headers["Cache-Control"] == "no-cache"464748def test_prerendered_shells_served(spa_client):49 r = spa_client.get("/docs")50 assert r.status_code == 200 and "prerendered docs" in r.text51 r = spa_client.get("/docs/errors") # no prerender → shell, still a known route52 assert r.status_code == 200 and "<div id=root>" in r.text53 r = spa_client.get("/limits")54 assert r.status_code == 200 and "prerendered limits" in r.text555657def test_unknown_route_is_404_with_shell(spa_client):58 r = spa_client.get("/this-page-does-not-exist")59 assert r.status_code == 40460 assert "<div id=root>" in r.text and "text/html" in r.headers["content-type"]61 r = spa_client.get("/dashboardx")62 assert r.status_code == 404636465def test_real_files_served(spa_client):66 r = spa_client.get("/favicon.svg")67 assert r.status_code == 200 and "svg" in r.headers["content-type"]686970def test_assets_immutable_and_gzipped(spa_client):71 r = spa_client.get("/assets/index-abc123.js", headers={"Accept-Encoding": "gzip"})72 assert r.status_code == 20073 assert r.headers["Cache-Control"] == "public, max-age=31536000, immutable"74 assert r.headers.get("Content-Encoding") == "gzip"75 assert r.headers["X-Frame-Options"] == "DENY"76 r = spa_client.get("/assets/missing-000.js")77 assert r.status_code == 40478 assert "Cache-Control" not in r.headers or "immutable" not in r.headers["Cache-Control"]798081def test_html_gets_csp_not_frame_options(spa_client):82 r = spa_client.get("/")83 csp = r.headers["Content-Security-Policy"]84 assert "default-src 'self'" in csp and "frame-ancestors 'none'" in csp and "cdn.jsdelivr.net" not in csp85 assert "X-Frame-Options" not in r.headers86 assert r.headers["Strict-Transport-Security"].startswith("max-age=")878889def test_api_paths_never_get_the_shell(spa_client):90 r = spa_client.get("/v1/does-not-exist")91 assert r.status_code == 404 and r.headers["content-type"].startswith("application/json")92 assert r.json()["error"]["code"] == "NOT_FOUND"93 r = spa_client.get("/v1/ping")94 assert r.status_code == 200 and r.json() == {"ok": True}95 r = spa_client.get("/openapi.json")96 assert r.status_code == 404 and r.headers["content-type"].startswith("application/json")97 r = spa_client.get("/swagger")98 assert r.status_code == 404 and r.headers["content-type"].startswith("application/json")99100101def test_login_redirect(spa_client):102 r = spa_client.get("/login", follow_redirects=False)103 assert r.status_code == 301 and r.headers["Location"] == "/signin"104105106def test_path_traversal_blocked(spa_client):107 r = spa_client.get("/../../etc/passwd")108 assert r.status_code in (404, 200)109 assert "root:" not in r.text110