refactor: 白板路由改 /wb 前缀,消除 HTML 与 REST 同路径冲突

问题:GET /whiteboard/{board_id} 同时被 REST(返回 JSON)与 main.py 的 HTML 页面
注册,FastAPI 按注册顺序匹配到 REST,导致浏览器访问拿到 JSON 而非前端页面。

改为按职责分命名空间,避免冲突:
- HTML 页面:/wb/{id}(main.py)、/wb-admin(main.py,Basic Auth)
- 公开 REST:GET /api/wb/{id}(前端 init 拉取初始笔画)
- WS:/ws/wb/{id}(实时同步 + 心跳)
- 管理 REST:GET /api/admin/wb、DELETE /api/admin/wb/{id}(Basic Auth)

前端 whiteboard.js / whiteboard_admin.js、测试脚本、README 路径同步更新。
旧 /whiteboard/* 路径不再注册(404)。
This commit is contained in:
zikai
2026-07-21 14:51:33 +00:00
parent 3284269399
commit 7188c62d3a
7 changed files with 44 additions and 41 deletions

View File

@@ -1,10 +1,13 @@
"""白板接口REST访问/管理)+ WebSocket实时同步
路由:
GET /whiteboard/{board_id} 公开:访问白板,不存在则新建
WS /ws/whiteboard/{board_id} 公开:实时协作 + 心跳
GET /api/admin/whiteboards Basic Auth管理页列表
DELETE /api/admin/whiteboards/{id} Basic Auth删除白板
GET /api/wb/{board_id} 公开:访问白板元数据,不存在则新建(前端 init 用)
WS /ws/wb/{board_id} 公开:实时协作 + 心跳
GET /api/admin/wb Basic Auth管理页列表
DELETE /api/admin/wb/{board_id} Basic Auth删除白板
HTML 页面 /wb/{id} 与管理页 /wb-admin 由 main.py 直接返回静态文件,
不在此 controller 注册,避免与 REST 同路径冲突。
"""
from __future__ import annotations
@@ -36,10 +39,10 @@ def _service(db: Session = Depends(get_db)) -> WhiteboardService:
# ---------------- 公开 REST ----------------
@router.get(
"/whiteboard/{board_id}",
"/api/wb/{board_id}",
response_model=WhiteboardOut,
summary="访问白板(不存在则新建)",
description="任何人凭 board_id 即可访问;不存在时自动创建空板并返回",
summary="访问白板元数据(不存在则新建)",
description="前端打开 /wb/{id} 页面后调本接口拉取初始笔画;不存在时自动创建空板。",
)
def get_whiteboard(board_id: str, service: WhiteboardService = Depends(_service)) -> WhiteboardOut:
return service.get_or_create(board_id)
@@ -48,7 +51,7 @@ def get_whiteboard(board_id: str, service: WhiteboardService = Depends(_service)
# ---------------- 管理 RESTBasic Auth ----------------
@router.get(
"/api/admin/whiteboards",
"/api/admin/wb",
response_model=WhiteboardListResponse,
summary="列出所有白板(需鉴权)",
description="供白板管理页使用board_id / 创建时间 / 修改次数 / 上次修改时间。",
@@ -64,7 +67,7 @@ def list_whiteboards(
@router.delete(
"/api/admin/whiteboards/{board_id}",
"/api/admin/wb/{board_id}",
summary="删除白板(需鉴权)",
description="删 DB 行,并关闭该 board 的所有在线 WebSocket 连接。",
)
@@ -81,7 +84,7 @@ def delete_whiteboard(
# ---------------- WebSocket公开实时同步 + 心跳) ----------------
@router.websocket("/ws/whiteboard/{board_id}")
@router.websocket("/ws/wb/{board_id}")
async def whiteboard_ws(websocket: WebSocket, board_id: str) -> None:
"""白板实时协作端点。

View File

@@ -8,10 +8,10 @@
GET /health -> 存活探针(公开)
GET /upload -> 上传页面(公开 HTML
GET /files -> 文件浏览页Basic Auth同 docs
GET /whiteboard/{id} -> 白板页面(公开,不存在则新建)
GET /whiteboard-admin -> 白板管理页Basic Auth同 docs
GET /wb/{id} -> 白板页面(公开,不存在则新建)
GET /wb-admin -> 白板管理页Basic Auth同 docs
GET /api/... -> 业务接口
WS /ws/whiteboard/{id} -> 白板实时同步(公开)
WS /ws/wb/{id} -> 白板实时同步(公开)
/static/... -> 前端静态资源JS/CSS
"""
@@ -189,12 +189,12 @@ def create_app() -> FastAPI:
"""文件浏览页Basic Auth同 docs列出/下载/删除已上传文件。"""
return _serve_static_html("file_browser.html")
@app.get("/whiteboard-admin", response_class=HTMLResponse)
@app.get("/wb-admin", response_class=HTMLResponse)
def whiteboard_admin_page(_: str = Depends(require_docs_auth)) -> HTMLResponse:
"""白板管理页Basic Auth同 docs查看/删除白板。"""
return _serve_static_html("whiteboard_admin.html")
@app.get("/whiteboard/{board_id}", response_class=HTMLResponse)
@app.get("/wb/{board_id}", response_class=HTMLResponse)
def whiteboard_page(board_id: str) -> HTMLResponse:
"""白板页面(公开):访问即协作,不存在则前端拉取时自动新建。"""
return _serve_static_html("whiteboard.html")