PR #10(视频号流式解密下载端点)在 owner 明确授权下**绕过 gate 合并**, 本 issue 记录合并时已知、经判定不阻塞的两条缺陷。 ## 一、CDN 建连失败逃逸为框架级 500(gate 标 major,本仓判 **P2**) `app/api/stream.py`:端点对「取 TikHub media 失败」和「`_reconcile_cdn_offset` 抛 `UpstreamDisconnected`」都做了异常转换,但 **CDN opener 的 await 外没有对应处理**。 `_UPSTREAM_FAIL` 只在响应体迭代器 `_iter_decrypted` 中使用。因此响应头发出前的 CDN 网络失败 会逃逸成框架级未处理异常,返回通用 500,而不是接口契约要求的 502 JSON。 **本仓 P1 两问**: - 会触发吗?会——CDN 网络失败是常见路径。 - 后果能接受吗?客户端收到 500 而非 502 JSON。**失败可观测**,不产出损坏数据、不静默出错。 按本仓 `internal` 红线(数据丢失 / 静默出错 / 崩溃 / 越权 / 损坏他人数据)不构成 P1, 属于「错误响应形式不符合契约」。 **修法**:给 CDN opener 的 await 套上与 media 失败同形的异常转换,返回 502 JSON。改动很小。 ## 二、`_open_cdn_stream_httpx` 重复构造 httpx 客户端(gate 标 minor) 同文件:函数先构造一个 `httpx.AsyncClient` 赋给 `client`,随后在未使用该实例的情况下 再次构造并覆盖同一变量。属于确定存在的重复对象构造,带来无谓开销与所有权歧义。 **注意**:这条是「预响应取消资源释放」那一轮修复引入的残留——把客户端所有权挪进 `try/finally` 时没删掉旧的构造语句。 **修法**:删掉第一次构造。 ## 背景:为什么在此处停下 该端点的 gate 连续跑了 6 轮,每轮都有 finding,但严重性单调下降: | 轮 | finding | 后果性质 | |---|---|---| | 1–3 | 重连逃逸 / 区间未对账 / 对账有豁免 | 产出能播但内容错位的 mp4(静默出错,真 P1) | | 4 | 对账维度不全 | 下载失败,可观测 | | 5 | 预响应取消导致并发配额泄漏 | 功能不可用,可观测 | | 6 | 本 issue 这两条 | 错误形式不规范 / 轻微浪费 | 真正会让调用方拿到坏文件而不自知的缺陷已在前五轮修完,并各自有变异注入验证过的测试锁死 (注入后精确变红、恢复后全绿)。合并时本地全量 **235 passed**,真实链路探活通过 (`POST /api/resolve` → `Range: bytes=0-131071` → HTTP 206 / 131072 字节 / 偏移 4..8 为 `ftyp`)。 owner 据此判断止损,授权绕过 gate 合并,本 issue 承接剩余两条。
Activity
zj1123581321 commentedon Sep 23, 2026
分诊复核(2026-09-23,pi 主脑在
cb1e2b9实测)两条缺陷都已在最新主干修复,本 issue 描述的是 PR #10 时期的形态(
_iter_decrypted那个函数如今已不存在)。实测证据:一、首窗 CDN 建连失败 → 已不再逃逸成 500
机理:
_read_window的except _UPSTREAM_FAIL(httpx.TransportError在内)+ 端点侧except UpstreamDisconnected → _json_http_error(502, ...)。修复出处:
ef9af01 fix(wechat_channels): 窗口 ConnectTimeout 纳入重试并去掉泄漏的 AsyncClient(#16)与8373dd1(分窗全读)。二、重复构造 httpx client → 已删
只剩一处构造(
ef9af01删掉了泄漏的那个);所有权由test_pre_response_cancel_during_cdn_open_closes_client锁住。结论:缺陷不可复现 —— 本 issue 的处置是关单,不派修复卡。
差距只在「回归锁」:这两条目前没有专门的锁测试(既有测试覆盖的是首窗 CDN 500 与后窗 ConnectTimeout),已派补锁卡覆盖这两个缺口,落地后关单。
Merge pull request #36 from zlxlabs/card/MediaResolverAPI-stream-lock…
zj1123581321 commentedon Sep 23, 2026
关单(2026-09-23,PR #36 合入 master
c5cec29)补锁落地,缺陷锁死:
tests/test_stream_boundary_locks.py::test_first_window_connect_error_retries_and_returns_502_json—— 首窗 CDN 传输层建连失败:502、!= 500、application/json、open_cdn_stream调用 ≥ 2(证明已被收进可重试链路而不是单次逃逸)。#11-2重复构造 client:master 上grep -n "httpx.AsyncClient(" app/api/stream.py仅剩第 89 行一处;所有权由既有test_pre_response_cancel_during_cdn_open_closes_client锁住,本轮未再加锁。_read_window的except _UPSTREAM_FAIL收窄成except UpstreamDisconnected→ 新用例转红assert 500 == 502;还原后全绿。测试命令:
uv run --extra dev python -m pytest tests/test_stream_boundary_locks.py -q→ 2 passed(在合入后的 master 上跑)。