Files
zTools2/tests/manual_whiteboard_kick.py
zikai ff2ad3fcb3 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 新增「路由约定」说明。
2026-07-27 15:42:47 +08:00

53 lines
1.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""验证删除白板时,在线 WS 连接被服务端踢出(收到 error 帧并断连)。"""
from __future__ import annotations
import asyncio
import json
import urllib.request
import websockets
BASE_WS = "ws://127.0.0.1:6867/api/ws/wb"
BOARD = "kicktest"
AUTH = "Basic YTo2NjUxMTMxNQ==" # a:66511315
async def main() -> None:
async with websockets.connect(f"{BASE_WS}/{BOARD}") as a:
await a.send(json.dumps({"type": "hello", "client_id": "A"}))
init = json.loads(await asyncio.wait_for(a.recv(), timeout=2))
assert init["type"] == "init"
print("A connected, init received")
# 通过 REST 删除白板(带 Basic Auth
req = urllib.request.Request(
f"http://127.0.0.1:6867/api/admin/wb/{BOARD}",
method="DELETE",
headers={"Authorization": AUTH},
)
with urllib.request.urlopen(req) as r:
print("delete response:", r.read().decode())
# A 应收到 error 帧随后连接关闭
try:
raw = await asyncio.wait_for(a.recv(), timeout=3)
msg = json.loads(raw)
print("A received:", msg)
assert msg["type"] == "error", "应收到 error 通知"
except (websockets.ConnectionClosed, asyncio.TimeoutError) as e:
print("连接关闭/超时:", e)
# 确认连接已断
try:
await asyncio.wait_for(a.recv(), timeout=2)
print("ERROR: 连接仍存活(应已断开)")
except websockets.ConnectionClosed:
print("连接已被服务端关闭 ✅")
except asyncio.TimeoutError:
print("连接未关闭但无消息(部分通过)")
if __name__ == "__main__":
asyncio.run(main())