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

@@ -8,8 +8,8 @@
const { el, toast, copyText } = window.ZK;
// ---------- 从 URL 解析 board_id ----------
// 路径形如 /whiteboard/{id}id 为 [a-zA-Z0-9_-]{1,64}
const m = location.pathname.match(/^\/whiteboard\/([^/]+)\/?$/);
// 路径形如 /wb/{id}id 为 [a-zA-Z0-9_-]{1,64}
const m = location.pathname.match(/^\/wb\/([^/]+)\/?$/);
let boardId = m ? decodeURIComponent(m[1]) : "default";
// 合法性兜底:前端非法字符直接回退到 default真正校验在服务端
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(boardId)) boardId = "default";
@@ -139,7 +139,7 @@
});
copyBtn.addEventListener("click", async () => {
const url = `${location.origin}/whiteboard/${boardId}`;
const url = `${location.origin}/wb/${boardId}`;
const ok = await copyText(url);
toast(ok ? "链接已复制" : "复制失败");
});
@@ -147,7 +147,7 @@
// ---------- WebSocket ----------
function wsUrl() {
const proto = location.protocol === "https:" ? "wss:" : "ws:";
return `${proto}//${location.host}/ws/whiteboard/${encodeURIComponent(boardId)}`;
return `${proto}//${location.host}/ws/wb/${encodeURIComponent(boardId)}`;
}
function connect() {
@@ -242,8 +242,8 @@
}
// ---------- 启动 ----------
// 先 GET /whiteboard/{id} 确保白板存在(不存在则服务端新建),再连 WS
fetch(`/whiteboard/${encodeURIComponent(boardId)}`, { headers: { accept: "application/json" } })
// 先 GET /api/wb/{id} 确保白板存在(不存在则服务端新建),再连 WS
fetch(`/api/wb/${encodeURIComponent(boardId)}`, { headers: { accept: "application/json" } })
.then((r) => r.ok ? r.json() : null)
.then((body) => {
if (body && Array.isArray(body.strokes)) {