fix(proxy): /plugins/ 合并脚本补 ETag + 304 短路 —— 省掉每次 11 MB 重下(档案 97)

问题(实测 2026-09-14):官方 `@deepseek-ai/dsh-client-modules` 把全部客户端插件拼成**一条
11,172,365 字节的脚本**(combo URL `/plugins/??<模块列表>&rev=<revision>`);我们给它下发
`no-cache`(档案 95,为"改了 UI 就能看到"),而实例**既不给 ETag 也不给 Last-Modified**
⇒ 浏览器"回源校验"退化成**每次全量重下 11 MB** —— 经 Cloudflare 实测 **114.87 秒**
(弱网/手机上直接表现为页面加载不出来)。

修法(只动 proxy.ts 一处,不改官方、不动 rev):
· 按 URL 派生强校验器 `ETag = sha1(targetPath)`,**只对 GET/HEAD + /plugins/ 且 URL 含 `rev=` 生效**
  (无 rev 一律跳过)。依据是官方契约:「**已公告响应不可变;未知组合或 revision 返回 404**」
  ⇒ (模块组合, rev) 唯一决定内容 ⇒ 同 URL 必同字节,故按 URL 派生 ETag 是安全的。
· 命中 `If-None-Match` 时 **直接回 304、完全不回源**(省的正是那 11 MB)。
· 未命中时行为与原先一致,只在既有缓存头区块多透出一个 `ETag`。

验证:
· 本机 `npm run verify` EXIT=0;服务器 `ci.sh` CI OK(48 pass / 0 fail);
· `scripts/verify-inject.cjs` 新增防回退断言「proxy.ts 有 /plugins/ ETag + 304 短路」;
· **端到端实测**:① 首次 200 / 11,172,365 B + `ETag="034a459a92…"`;② 带 If-None-Match → **304 / 0 B** ✅

⚠️ 顺带记录:本仓库 `core.autocrlf` 会在 git 触碰后把工作区文件改成 CRLF ⇒ 脚本化改文件必须
**行尾自适应**(本轮 `proxy.ts` 的多行匹配因此失配过一次)。
This commit is contained in:
admin committed 2026-09-14 22:46:40 +08:00
1 parent 53b8eff870
commit cc1dc5c9a8
2 files changed
+40

No files matched your search

+12
View File
@@ -72,6 +72,18 @@ if (fs.existsSync(PROXY_SRC)) {
} else {
console.log(' ✓ proxy.ts 缓存治理完整(/plugins/ 与 text/html 均 no-cache)')
}
// 档案 97:/plugins/ 必须有**由 URL 派生的 ETag + 304 短路** ——
// 那条合并脚本 11 MB、未压缩,只靠 no-cache 会让浏览器**每次全量重下**
// (实测经 CF 114.87 s)。rev 即修订标识 ⇒ 用 URL 派生 ETag 安全。
const hasEtag = /const pluginEtag =/.test(src) && /createHash\('sha1'\).update\(targetPath\)/.test(src)
const hasShort = /writeHead\(304, \{ etag: pluginEtag/.test(src)
const etagOut = /headers\.etag = pluginEtag/.test(src)
if (!hasEtag || !hasShort || !etagOut) {
console.log(` ✗ proxy.ts 缺 /plugins/ 的 ETag 条件请求短路(etag=${hasEtag} 304短路=${short} 透出=${etagOut})`.replace('${short}', String(hasShort)))
bad++
} else {
console.log(' ✓ proxy.ts 有 /plugins/ ETag + 304 短路(省掉每次 11 MB 重下)')
}
}
console.log(bad ? '结论:' + bad + ' 项不合格 ❌ —— 别推上线' : '结论:全部合格 ✅')