fix(preview+pipeline): 资产键编码归一——7 张全角名图片预览 404 修复;证据文档叙述修正
spec 复审发现(浏览器可见缺陷):manifest 资产行 exact_key 有 7 例为裸形 (文件名含全角括号/顿号/间隔号)——html/redirect 键源数据侧已编码、asset 键来自文件名本体是裸形;浏览器对裸非 ASCII 一律百分号编码后发请求,预览 按请求字节逐字匹配 → 裸键永不命中 → 两页 3 张图破图(dist 文件在盘; 生产面 nginx 先解码不受影响)。修补 pipeline.toManifestRoute:exact_key 归一为 URL 线形(可打印 ASCII 原样、其余 UTF-8 百分号编码大写 hex), target_file 仍盘上裸名、DB/渲染快照域不变。 回归三层:build-pipeline 注入裸全角资产行(红验证);preview-server 2c 非 ASCII redirect → Location → 资产终端 200;e2e 断言 ④c(7 条全查 跟随到终端 200)+ ⑦c(manifest 2772 键全 ASCII 不变量)。spec 复审复跑 (新库全链 job e059bf41)23/23 PASS,浏览器实测 3 张原破图全部加载。 证据文档:§5.2 失败计数修正(5×500+2×mojibake=7 例)、§2 ①c 措辞对齐 断言实义(抽前 3 标题)、§5.5 修补记录、计时/产物/job 面更新至复跑值。 验证:vitest 382 + 主题 26 全绿(408);typecheck 过;lint 裸跑零告警。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -344,6 +344,25 @@ function buildRobots(origin: string): string {
|
||||
return `User-agent: *\nAllow: /\n\nSitemap: ${origin}/sitemap.xml\n`
|
||||
}
|
||||
|
||||
/**
|
||||
* exact_key 线形归一(URL wire form):可打印 ASCII(含既有 %xx 序列的字面 %)原样,
|
||||
* 其余码位按 UTF-8 百分号编码(大写 hex——WHATWG URL 解析器/浏览器的编码形态;空格
|
||||
* 同路编码为 %20)。Task 8 spec 复审修补:asset 路由的 routePath 来自文件名本体(真实
|
||||
* hesupipe 7 例含全角括号/顿号/间隔号),html/redirect 键在源数据侧已是编码形、asset
|
||||
* 键是裸形——预览按请求字节逐字匹配(浏览器对裸非 ASCII 一律百分号编码后发送),裸键
|
||||
* 永不命中 → 图片 404、redirect Location 跟随断裂。归一只动 manifest 键(服务权威面);
|
||||
* target_file 仍是盘上文件名(裸形——文件系统域不解码),route_registry/渲染快照域
|
||||
* 不变(DB 键保持导入原串)。
|
||||
*/
|
||||
function wireKeyOf(key: string): string {
|
||||
let out = ''
|
||||
for (const ch of key) {
|
||||
const code = ch.codePointAt(0)!
|
||||
out += code > 0x20 && code <= 0x7e ? ch : encodeURIComponent(ch)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/** route-manifest 行映射:exact_key 带查询形态;target_file 派生映射;redirect 带 location */
|
||||
function toManifestRoute(r: RouteEntry, assetsByPath: Map<string, AssetEntry>): RouteManifestRoute {
|
||||
// redirect 行 redirectStatus 是权威(targetStatus 同值兜底——数据面两处冗余)
|
||||
@@ -355,7 +374,7 @@ function toManifestRoute(r: RouteEntry, assetsByPath: Map<string, AssetEntry>):
|
||||
)
|
||||
}
|
||||
const row: RouteManifestRoute = {
|
||||
exact_key: r.queryKey === null ? r.routePath : `${r.routePath}?${r.queryKey}`,
|
||||
exact_key: wireKeyOf(r.queryKey === null ? r.routePath : `${r.routePath}?${r.queryKey}`),
|
||||
query_policy: r.queryPolicy,
|
||||
query_key: r.queryKey,
|
||||
kind: r.routeKind,
|
||||
|
||||
Reference in New Issue
Block a user