feat: 所有入口统一到 /api/ 前缀

将 zTools2 托管的页面/静态/探针/WebSocket 路由全部从顶级路径迁移到 /api/ 下:
- 页面:/pdf -> /api/pdf、/pdf-admin -> /api/pdf-admin、/upload -> /api/upload、
  /files -> /api/files-page、/wb/{id} -> /api/wb-page/{id}、/wb-admin -> /api/wb-admin
  (页面类加 -page 后缀以规避同名 REST API /api/files、/api/wb/{id})
- 静态资源:/static -> /api/static
- 探针:/health -> /api/health
- WebSocket:/ws/wb/{id} -> /api/ws/wb/{id}
- 前端 HTML 壳与 JS 中的资源/页间链接/WS URL 同步更新
- 手动测试脚本 BASE_WS 同步

这样反代与 vite proxy 只需一条 /api/ 规则即可转发全部入口;
前端 iframe 用同源相对路径 /api/pdf,与环境无关,不再误打到其它环境域名。
README 新增「路由约定」说明。
This commit is contained in:
2026-07-27 15:42:47 +08:00
parent 729c77e98b
commit ff2ad3fcb3
13 changed files with 75 additions and 60 deletions

View File

@@ -153,8 +153,10 @@ def create_app() -> FastAPI:
app.include_router(pdf_router)
# 前端静态资源JS/CSSHTML 壳由下面的具名路由返回,便于各自挂 Basic Auth
# 统一 /api/ 前缀:所有 zTools2 入口(页面/静态/探针/WS/API都在 /api/ 下,
# 反代与 vite proxy 只需一条 /api/ 规则即可转发,与环境无关
if _STATIC_DIR.is_dir():
app.mount("/static", StaticFiles(directory=str(_STATIC_DIR)), name="static")
app.mount("/api/static", StaticFiles(directory=str(_STATIC_DIR)), name="static")
# 受 Basic Auth 保护的文档接口
@app.get("/openapi.json", tags=["docs"], summary="OpenAPI 文档(需鉴权)")
@@ -177,12 +179,12 @@ def create_app() -> FastAPI:
def root() -> PlainTextResponse:
return PlainTextResponse(f"zikai {app.version}\n")
@app.get("/health", tags=["meta"], summary="存活探针")
@app.get("/api/health", tags=["meta"], summary="存活探针")
def health() -> dict:
return {"status": "ok"}
@app.get(
"/upload",
"/api/upload",
response_class=HTMLResponse,
tags=["pages"],
summary="上传页面",
@@ -192,7 +194,7 @@ def create_app() -> FastAPI:
return HTMLResponse(render_upload_html())
@app.get(
"/files",
"/api/files-page",
response_class=HTMLResponse,
tags=["pages"],
summary="文件浏览页(需鉴权)",
@@ -202,7 +204,7 @@ def create_app() -> FastAPI:
return _serve_static_html("file_browser.html")
@app.get(
"/wb-admin",
"/api/wb-admin",
response_class=HTMLResponse,
tags=["pages"],
summary="记事本管理页(需鉴权)",
@@ -212,17 +214,17 @@ def create_app() -> FastAPI:
return _serve_static_html("whiteboard_admin.html")
@app.get(
"/wb/{board_id}",
"/api/wb-page/{board_id}",
response_class=HTMLResponse,
tags=["pages"],
summary="记事本页面",
description="公开访问的共享文本记事本,不存在则自动新建;实时协作走 WS /ws/wb/{id}",
description="公开访问的共享文本记事本,不存在则自动新建;实时协作走 WS /api/ws/wb/{id}",
)
def whiteboard_page(board_id: str) -> HTMLResponse:
return _serve_static_html("whiteboard.html")
@app.get(
"/pdf",
"/api/pdf",
response_class=HTMLResponse,
tags=["pages"],
summary="PDF 转换页面",
@@ -232,7 +234,7 @@ def create_app() -> FastAPI:
return _serve_static_html("pdf.html")
@app.get(
"/pdf-admin",
"/api/pdf-admin",
response_class=HTMLResponse,
tags=["pages"],
summary="PDF 转换管理页(需鉴权)",