Files
jackyu66gitandCursor 7ab9add5dd
ci / h5 (push) Canceled after 0s
ci / api (push) Canceled after 0s
ci / ess-docs (push) Canceled after 0s
feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 02:26:16 +08:00

64 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""Serve admin-h5 dist for /psy/admin (nginx strips prefix → this listens on :8003)."""
from __future__ import annotations
import mimetypes
import os
import sys
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
ROOT = Path(__file__).resolve().parent
DIST = ROOT / "apps" / "admin-h5" / "dist"
PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8003
class Handler(BaseHTTPRequestHandler):
def log_message(self, fmt: str, *args) -> None:
sys.stderr.write("%s - %s\n" % (self.address_string(), fmt % args))
def do_GET(self) -> None: # noqa: N802
path = self.path.split("?", 1)[0]
if path in ("", "/"):
path = "/index.html"
# security: no path escape
rel = path.lstrip("/")
candidate = (DIST / rel).resolve()
if not str(candidate).startswith(str(DIST.resolve())):
self.send_error(400)
return
if candidate.is_file():
self._file(candidate)
return
# hashed asset miss → 404 (not SPA), so MIME errors are obvious
if "/assets/" in path or path.endswith((".js", ".css", ".map", ".png", ".svg", ".ico", ".woff2")):
self.send_error(404)
return
index = DIST / "index.html"
if index.is_file():
self._file(index)
return
self.send_error(404)
def _file(self, file_path: Path) -> None:
data = file_path.read_bytes()
ctype, _ = mimetypes.guess_type(str(file_path))
self.send_response(200)
self.send_header("Content-Type", ctype or "application/octet-stream")
self.send_header("Content-Length", str(len(data)))
self.send_header("Cache-Control", "no-cache" if file_path.name == "index.html" else "public, max-age=86400")
self.end_headers()
self.wfile.write(data)
def main() -> None:
if not DIST.is_dir():
raise SystemExit(f"admin dist missing: {DIST} (run npm run build:admin)")
httpd = ThreadingHTTPServer(("127.0.0.1", PORT), Handler)
print(f"admin-h5 on http://127.0.0.1:{PORT}/ (nginx → /psy/admin/)", flush=True)
httpd.serve_forever()
if __name__ == "__main__":
main()