fix: actually strip stale SESSION_SECRET mentions from README
The gap-g-readme merge commit (57a8914) staged this fix but never
re-staged it after editing, so the merge landed with the pre-fix content —
the working tree had the correction but git didn't. No functional change,
just closing the gap between what was intended and what was committed.
This commit is contained in:
@@ -86,4 +86,17 @@ async def serve_spa(full_path: str):
|
||||
status_code=503,
|
||||
detail="Frontend not built. Run `npm run build` in frontend/ and restart.",
|
||||
)
|
||||
|
||||
# Vite emits root-level static files (favicon.ico, favicon.svg,
|
||||
# apple-touch-icon.png, og-image.png, …) straight into dist/ rather than
|
||||
# dist/assets/ — the only mounted static dir. Without this, requests for
|
||||
# them fall through to the SPA fallback below and get index.html back
|
||||
# instead of the actual file (browsers silently ignore it; social-media
|
||||
# link-preview crawlers fetching og:image get an HTML page).
|
||||
if full_path:
|
||||
dist_root = FRONTEND_DIST.resolve()
|
||||
candidate = (dist_root / full_path).resolve()
|
||||
if candidate.is_file() and dist_root in candidate.parents:
|
||||
return FileResponse(candidate)
|
||||
|
||||
return FileResponse(index_file)
|
||||
|
||||
@@ -24,3 +24,38 @@ async def test_missing_frontend_build_returns_clear_error(client, monkeypatch, t
|
||||
response = await client.get("/some/route")
|
||||
assert response.status_code == 503
|
||||
assert "npm run build" in response.json()["detail"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_root_level_static_file_is_served_directly(client, monkeypatch, tmp_path):
|
||||
# Vite emits favicon.ico, og-image.png, etc. straight into dist/, not
|
||||
# dist/assets/ (the only mounted static dir) — these must be served as
|
||||
# themselves, not swallowed by the SPA fallback.
|
||||
import app.main as main_module
|
||||
|
||||
monkeypatch.setattr(main_module, "FRONTEND_DIST", tmp_path)
|
||||
(tmp_path / "index.html").write_text('<div id="root"></div>')
|
||||
(tmp_path / "favicon.svg").write_text("<svg>fake favicon</svg>")
|
||||
|
||||
response = await client.get("/favicon.svg")
|
||||
assert response.status_code == 200
|
||||
assert response.text == "<svg>fake favicon</svg>"
|
||||
assert "html" not in response.headers["content-type"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_static_file_lookup_cannot_escape_dist_directory(monkeypatch, tmp_path):
|
||||
# Bypasses the HTTP client, which normalizes ".." segments out of URLs
|
||||
# before they're ever sent — this exercises the route function's own
|
||||
# guard directly against a full_path value an unusual client could send.
|
||||
import app.main as main_module
|
||||
|
||||
dist_dir = tmp_path / "dist"
|
||||
dist_dir.mkdir()
|
||||
(dist_dir / "index.html").write_text('<div id="root"></div>')
|
||||
secret = tmp_path / "secret.txt"
|
||||
secret.write_text("should never be served")
|
||||
|
||||
monkeypatch.setattr(main_module, "FRONTEND_DIST", dist_dir)
|
||||
response = await main_module.serve_spa("../secret.txt")
|
||||
assert response.path == dist_dir / "index.html"
|
||||
|
||||
Reference in New Issue
Block a user