fix(demo-service): force inline Content-Disposition to prevent download

- All responses (HTML, CSS, JS, images) now have Content-Disposition: inline
- Add Cache-Control: no-store to bust any cached attachment response
- 401/404 error pages: inline, text/html, no-store
This commit is contained in:
Junv (via Hermes)
2026-06-14 11:49:52 +10:00
parent cc0fe77749
commit 031f39bae6
+19 -5
View File
@@ -144,11 +144,17 @@ async def site_content(path: str = "", request: Request = None):
site_name = parts[0] site_name = parts[0]
sub = parts[1] if len(parts) > 1 else "" sub = parts[1] if len(parts) > 1 else ""
if not site_name or not site_exists(site_name): if not site_name or not site_exists(site_name):
return HTMLResponse(AUTH_REQUIRED_HTML, status_code=404) resp = HTMLResponse(AUTH_REQUIRED_HTML, status_code=404)
resp.headers["Content-Disposition"] = "inline"
resp.headers["Cache-Control"] = "no-store"
return resp
visible = is_site_visible(site_name) visible = is_site_visible(site_name)
if not visible: if not visible:
if not check_auth(request): if not check_auth(request):
return HTMLResponse(AUTH_REQUIRED_HTML, status_code=401) resp = HTMLResponse(AUTH_REQUIRED_HTML, status_code=401)
resp.headers["Content-Disposition"] = "inline"
resp.headers["Cache-Control"] = "no-store"
return resp
site_dir = DEMO_ROOT / site_name site_dir = DEMO_ROOT / site_name
target = (site_dir / sub) if sub else (site_dir / "index.html") target = (site_dir / sub) if sub else (site_dir / "index.html")
if not target.exists(): if not target.exists():
@@ -159,15 +165,23 @@ async def site_content(path: str = "", request: Request = None):
target = p target = p
break break
if not target.exists(): if not target.exists():
return HTMLResponse(AUTH_REQUIRED_HTML, status_code=404) resp = HTMLResponse(AUTH_REQUIRED_HTML, status_code=404)
resp.headers["Content-Disposition"] = "inline"
resp.headers["Cache-Control"] = "no-store"
return resp
if target.is_dir(): if target.is_dir():
target = target / "index.html" target = target / "index.html"
if not target.exists(): if not target.exists():
return HTMLResponse(AUTH_REQUIRED_HTML, status_code=404) resp = HTMLResponse(AUTH_REQUIRED_HTML, status_code=404)
resp.headers["Content-Disposition"] = "inline"
resp.headers["Cache-Control"] = "no-store"
return resp
# HTML files render inline; others (CSS, JS, images) are served as files # HTML files render inline; others (CSS, JS, images) are served as files
if target.suffix == ".html": if target.suffix == ".html":
return HTMLResponse(target.read_text()) return HTMLResponse(target.read_text())
return FileResponse(target) resp = FileResponse(target)
resp.headers["Content-Disposition"] = "inline"
return resp
@app.get("/api/sites") @app.get("/api/sites")
def list_sites(request: Request): def list_sites(request: Request):