feat(chat): 页面级 basePath 引导(路径模式静态面)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
"""chat.html 静态面前缀守卫(spec 2026-10-19 §4):页面级 __BASE_PATH__ 引导。
|
||||
|
||||
chat 是页面而非嵌入脚本(与 widget.js 的脚本地址自推导不同),由 chat.html
|
||||
head 内联引导脚本按 location.pathname 推导 basePath 并动态装载 css/js/
|
||||
avatar;Host 模式(根路径 "/")推导为空串,所有引用零变化。守卫四点:
|
||||
引导脚本在场且走正则白名单 match、静态标签不再绝对引用、引导块零
|
||||
innerHTML(拼接安全防线 §2/§3)、chat.js 端点构造全部经 __BASE_PATH__。
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
STATIC = Path(__file__).resolve().parent.parent / "static"
|
||||
|
||||
|
||||
def read(rel):
|
||||
return (STATIC / rel).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_引导脚本存在且定义_BASE_PATH():
|
||||
src = read("chat.html")
|
||||
assert "__BASE_PATH__" in src
|
||||
# 代码锚(非注释):base 推导必须走正则白名单 match
|
||||
assert "location.pathname.match(" in src
|
||||
|
||||
|
||||
def test_不再有静态绝对引用标签():
|
||||
src = read("chat.html")
|
||||
assert 'href="/static/' not in src
|
||||
assert 'src="/static/js/' not in src
|
||||
assert 'src="/api/public/avatar"' not in src
|
||||
|
||||
|
||||
def test_引导脚本零innerHTML_拼接安全防线():
|
||||
# 安全防线 §2/§3:base 只做 URL 属性赋值,绝不拼 HTML——
|
||||
# 断言首个内联 <script>...</script> 块(引导脚本)内无 innerHTML
|
||||
src = read("chat.html")
|
||||
boot = src.split("<script>", 1)[1].split("</script>", 1)[0]
|
||||
assert "innerHTML" not in boot
|
||||
|
||||
|
||||
def test_chatjs_端点全部走_BASE_PATH():
|
||||
src = read("js/chat.js")
|
||||
assert "__BASE_PATH__" in src
|
||||
assert 'fetch("/api/' not in src
|
||||
Reference in New Issue
Block a user