1
T-253
ila edited this page 2026-08-07 16:37:00 +08:00
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.

同步来源:docs/tasks/T-253.md · commit afc651f75a3a


id: T-253 title: 修复 PDD ps 分享链接重定向被误判为网络失败 phase: 2 deps:

  • T-252 status: DONE created: 2026-07-30 context_ref: e6d4209 work_branch: null write_paths:
  • docs/tasks/T-253.md
  • docs/current-state.md
  • android-buyer/app/build.gradle.kts
  • android-buyer/app/src/main/**
  • android-buyer/app/src/test/**

问题 / 背景

T-252 上线后,任务 09240616-5d87-4ab1-a37a-57949725f8b2 仍以 CANDIDATE_SHARED_LINK_NETWORK_FAILED 结束。拼多多分享得到的 URL 形如 https://mobile.yangkeduo.com/goods2.html?ps=<opaque-token>,首个 URL 没有 goods_id。

现场请求证明该 ps 是不透明分享令牌:PDD 对首个请求返回小体积 307,并在同一 受信域名的 Location URL 中携带唯一 goods_id。Android 解析器虽然已经关闭 OkHttp 自动跳转并实现受控重定向,却在读取 Location 前调用 readByteArray(65537);Okio 会把该参数解释为“必须读取指定字节数”,小于该长度的 正常响应因此抛出 EOFException,随后被泛化成网络失败。

本任务修复响应处理顺序和有界正文读取,不把 ps 猜测、散列或保存成商品身份。

根因与边界

  • ps 只用于向 PDD 请求一次受控解析,不能代替稳定 goods_id,也不能用于 Admin 下单授权。
  • 301/302/303/307/308 的商品身份来源只能是经过 HTTPS 和 host allowlist 校验的 Location;跳转响应正文不参与身份提取。
  • 只有非跳转响应才允许检查正文;正文最多读取 64 KiB,并额外探测一个字节判断超限。 小于上限的正常正文不得触发 EOFException,超限正文不得参与身份推断。
  • 保留 T-252 的 PDD host allowlist、最多三次跳转、6 秒调用预算、失败码和原始分享 文本不落盘/不上传边界。
  • 不增加第三方解析服务,不让 VLM 推测 goods_id,不改变候选搜索轮次和下单边界。

方案

  1. 重排 resolver:直接链接仍优先本地解析;收到跳转响应后先校验 Location,从 下一跳 URL 提取 goods_id 或继续受控跳转,不读取响应正文。
  2. 将 OkHttp 正文读取改为“最多读取上限加一字节”,避免固定长度读取在 EOF 时抛错; 超限正文按无可用身份处理。
  3. 增加 OkHttp Response 级回归测试,覆盖小体积 307、ps 到 goods_id、小体积 200 正文、超限正文以及外域跳转拒绝。
  4. 提升 Android 构建版本,执行 Debug/Release 单测、lint 和 APK 构建。

验收要点

  • goods2.html?ps=<opaque-token> 返回小体积 307 时,不读取跳转正文且不会抛 EOFException。
  • 同域 Location 中的唯一 goods_id 被解析为规范商品身份,不发起不必要的 第二个网络请求。
  • 外域、非 HTTPS、缺失或超过三次的跳转继续 fail-closed。
  • 小于 64 KiB 的 2xx 正文可正常解析;大于 64 KiB 的正文不用于身份提取。
  • 真正的 I/O 异常才映射为 CANDIDATE_SHARED_LINK_NETWORK_FAILED。
  • Android Debug/Release 单测、lint 和构建通过。

执行记录

  • 2026-07-30:用用户提供的真实 ps 分享链接只读复现。PDD 返回 307,受信 Location 含唯一 goods_id;本地代码审计定位到固定长度响应读取导致的 EOFException。文档不记录原始分享令牌。
  • 2026-07-30:resolver 对跳转响应改为先验证 Location 并直接提取下一跳 goods_id,不再读取跳转正文;普通响应改用 OkHttp peekBody 最多读取 64 KiB 加一字节,底层响应在 transport 返回前可靠关闭。
  • 2026-07-30:增加真实 OkHttp Response 级小体积跳转、不可读跳转正文、小体积 成功正文和超限正文回归测试。Debug/Release 各 235 项 App 单测零失败,两个变体 lint 和 APK 构建通过;根 init.ps1 及全部 Go 后端测试通过。生成 Android 1.4.18 (23) Debug APK。
  • 2026-07-30:通过 USB 在 OnePlus PKG110 Android 16/API 36 上覆盖安装 1.4.18 (23) 并正常启动 MainActivity;采购无障碍、悬浮窗、通知和 Shizuku 权限均保持启用。