Files
Genarrative/docs/technical/PUZZLE_IMAGE_ASSET_PROXY_FIX_2026-04-27.md
2026-05-08 20:48:29 +08:00

3.0 KiB
Raw Blame History

拼图生成图片读取链路修复

日期:2026-04-27

更新:2026-05-08

背景

拼图结果页的“生成或更换图片”会在 api-server 中调用 DashScope 生成图片,再把候选图上传到 OSS最终以 /generated-puzzle-assets/... 旧兼容路径写回 PuzzleGeneratedImageCandidate.image_src 与草稿封面字段。

历史排查曾发现拼图图片写入路径已经进入 platform-oss::LegacyAssetPrefix::PuzzleAssets,但后端 Axum 旧资源代理和 Vite 本地代理没有挂载 /generated-puzzle-assets。当时的处理口径是补旧资源代理。

当前 WP-DEL 后,旧 /generated-* 直读代理已经物理删除;/generated-puzzle-assets/... 只允许作为 legacyPublicPath / OSS object key 标识。浏览器不能再直接请求该路径,必须通过 /api/assets/read-url?legacyPublicPath=... 换取短期签名 URL 后预览。

修复口径

  1. platform-oss::LEGACY_PUBLIC_PREFIXES 必须包含 generated-puzzle-assets保持直传票据、服务端上传、read-url 支持列表和错误提示同一口径。
  2. src/services/assetReadUrlService.tsisGeneratedLegacyPath(...) 需要同时识别 /generated-puzzle-assets/...generated-puzzle-assets/...。后者可能来自 object key 形态的历史字段。
  3. ResolvedAssetImage / useResolvedAssetReadUrl 在签名 URL 返回前不能把裸 /generated-*generated-* 写进 <img src>
  4. refreshKey 只能用于跳过前端签名 URL 缓存并重新请求 /api/assets/read-url,不能再给 OSS V4 签名 URL 追加 _v 等额外 queryOSS 会把 query 纳入签名,额外参数会让新生成图变成 403/破图。
  5. 历史素材被选为参考图后,参考图小预览也必须走 ResolvedAssetImage,不能使用裸 <img src="/generated-*">
  6. 禁止恢复 /generated-puzzle-assets/{*path} Axum 路由或 Vite 直读代理;正式读取统一走 /api/assets/read-url

后续约束

  1. 任何新增 LegacyAssetPrefix 都必须同时检查:
    • platform-oss 前缀枚举
    • platform-oss::LEGACY_PUBLIC_PREFIXES
    • /api/assets/read-url 入参解析
    • 前端 isGeneratedLegacyPath(...) 是否能识别
  2. 拼图候选图 JSON 仍保持 SpacetimeDB 持久化结构 PuzzleGeneratedImageCandidate 的 snake_case 字段,不把 HTTP camelCase 响应结构写入 draft_json
  3. 图片生成、OSS 读写和外部参考图解析继续留在 api-server,不能下沉到 SpacetimeDB reducer。
  4. 如果图片组件需要刷新 generated 私有资源,优先让 refreshKey 触发重新换签;不要修改已返回的 signedUrl

验收

  1. npm run test -- src\services\assetReadUrlService.test.ts src\hooks\useResolvedAssetReadUrl.test.tsx src\components\puzzle-result\PuzzleResultView.test.tsx
  2. cargo test -p platform-oss --manifest-path server-rs\Cargo.toml
  3. npm run check:encoding
  4. npm run api-server 重启后检查 /healthz,再点击拼图结果页“生成或更换图片”,候选图应能写回并正常展示。