diff --git a/home-apps/demo-service/service.py b/home-apps/demo-service/service.py index 81d5e8e..df97fa6 100644 --- a/home-apps/demo-service/service.py +++ b/home-apps/demo-service/service.py @@ -127,6 +127,29 @@ def error_resp(status_code: int = 404) -> HTMLResponse: return resp +# ── Static file fallback ───────────────────────────── +def _find_static_file(path: str): + """Try to locate a static file (image, css, js, etc.) referenced + from a site's HTML as a root-relative URL (e.g. /image.jpg from page /site-name). + Searches all site directories for a matching filename. + Returns (site_name, sub_path) or None.""" + filename = path.rsplit("/", 1)[-1] + if not filename or "." not in filename: + return None + ext = filename.rsplit(".", 1)[-1].lower() + if ext not in ("jpg", "jpeg", "png", "gif", "webp", "css", "js", "svg", "ico", "woff2", "pdf"): + return None + meta = _db.load_all() + for name in sorted(meta.get("sites", {}).keys()): + site_dir = DEMO_ROOT / name + if not site_dir.is_dir(): + continue + candidate = site_dir / filename + if candidate.exists() and candidate.is_file(): + return (name, filename) + return None + + # ─── File Helpers (NFS safe — no rename) ───────────── def sync_visibility(name: str): """Sync the on-disk index.html based on visibility mode.""" @@ -186,7 +209,17 @@ async def site_content(path: str = "", request: Request = None): info = _db.get(site_name) if not info: - return error_resp(404) + # ── Fallback: if the path doesn't match a site name, it might be + # a static file (image, css, js) referenced from a site's HTML. + # Try to find it in any site directory. + found = _find_static_file(path) + if found: + site_name, sub = found + info = _db.get(site_name) + if not info: + return error_resp(404) + else: + return error_resp(404) visibility = info["visibility"] user = check_auth(request)