Spaces:
Sleeping
Sleeping
| """ | |
| Viewer HTML rendering helpers. | |
| Separated from app.py so the factory stays under 150 lines. | |
| """ | |
| import os | |
| import secrets | |
| import base64 | |
| from flask import make_response | |
| def make_viewer_response(base_dir: str): | |
| """ | |
| Read src/viewer/index.html, inject nonce + version + token, set CSP headers. | |
| Returns a Flask Response object ready to send to the client. | |
| Raises an exception if the template file is missing. | |
| """ | |
| template_path = os.path.join(base_dir, "viewer", "index.html") | |
| with open(template_path, "r", encoding="utf-8") as f: | |
| template = f.read() | |
| nonce = base64.urlsafe_b64encode(secrets.token_bytes(16)).decode("utf-8").rstrip("=") | |
| # D2.2: Never embed the raw AGENTCACHE_SECRET in page source. | |
| # Replace the placeholder with an empty string — the viewer authenticates | |
| # via the Authorization header set programmatically after load. | |
| html = ( | |
| template | |
| .replace("__AGENTCACHE_VIEWER_NONCE__", nonce) | |
| .replace("__AGENTCACHE_VERSION__", "0.9.8") | |
| .replace("__AGENTCACHE_AUTO_TOKEN__", "") | |
| ) | |
| csp = "; ".join([ | |
| "default-src 'none'", | |
| "base-uri 'none'", | |
| "frame-ancestors 'self' https://huggingface.co https://*.hf.space", | |
| "object-src 'none'", | |
| "form-action 'none'", | |
| f"script-src 'nonce-{nonce}'", | |
| "script-src-attr 'none'", | |
| "style-src 'unsafe-inline'", | |
| ( | |
| "connect-src 'self' https: http://localhost:* http://127.0.0.1:* " | |
| "wss: ws://localhost:* ws://127.0.0.1:* wss://localhost:* wss://127.0.0.1:*" | |
| ), | |
| "img-src 'self' data:", | |
| "font-src 'self'", | |
| ]) | |
| res = make_response(html) | |
| res.headers["Content-Type"] = "text/html; charset=utf-8" | |
| res.headers["Content-Security-Policy"] = csp | |
| res.headers["Cache-Control"] = "no-cache" | |
| return res | |