Repository navigation
fix(mobile): 延迟压缩头提交后不再二次写头 - #165
Closed
mexiaosqwq wants to merge 1 commit into
Closed
mexiaosqwq wants to merge 1 commit into
mexiaosqwq wants to merge 1 commit into
Conversation
宿主 webserver 开启 compression: gzip 时,patchedWriteHead 在 flush(this) 提交延迟头之后,this.headersSent 已为 true 却仍把这次状态码重入交给原生 writeHead,同一次响应出现第二次写头,抛 ERR_HTTP_HEADERS_SENT;宿主 dispatch 捕获后 res.destroy(),客户端表现为 fetch failed / ECONNRESET。 flush() 改为返回是否提交了延迟头;patchedWriteHead 在该调用提交后遇到纯 状态码重入时直接返回,等同 Node _implicitHeader 在 _header 已设置时的 no-op。带 headers 的显式第二次 writeHead 仍按原生抛错。 重建 lib/compress.js 与 lib/compress.js.map,并在 test-mobile-server-streams.mjs 增加按宿主 gzip 包装形状复现的回归用例。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
宿主 webserver 开启
compression: gzip(默认 1024B 阈值)时,内置移动插件对「小 JSON + Content-Length」响应抛ERR_HTTP_HEADERS_SENT,客户端表现为fetch failed/ECONNRESET(例如 claude-style 的sendJson接口,以及本插件自己的会话删除 JSON 错误响应)。根因
tools/mobile-server/compress.js的patchedWriteHead()先调用flush(this)用origWriteHead提交延迟头;随后this.headersSent已为 true,但仍落到return origWriteHead.apply(this, args),同一次响应第二次写头。触发路径:
compression的on-headers包装把writeHead的头部并入响应头表,只把 statusCode 传给下一层;Content-Encoding,插件据res.getHeaders()仍判定可以延迟;res.end()时宿主compression的 end 代理补一次隐式writeHead(statusCode);flush()已把延迟头发出,随后再次origWriteHead→ERR_HTTP_HEADERS_SENT;res.destroy(),客户端连接中断。≥1024B 的响应由宿主压缩接管(
Content-Encoding已设置,插件不延迟),没有Content-Length的分块响应同样由宿主处理,所以只有「小 JSON + Content-Length」这一类路径命中。改动
tools/mobile-server/compress.js:flush()返回是否提交了延迟头;patchedWriteHead()在该调用提交后遇到纯状态码重入时直接返回,等同 Node_implicitHeader在_header已设置时的 no-op。带 headers 的显式第二次writeHead仍按原生抛错。app/src/main/assets/builtin-plugins/dsh-web-mobile/lib/compress.js与.map:由node tools/apply-mobile-client-patches.mjs --server tools/mobile-plugin-upstream/lib --write重建。tools/test-mobile-server-streams.mjs:新增回归用例,按宿主 gzip 的包装形状(头部并入响应头表、end 时隐式写头)复现该组合。验证
ERR_HTTP_HEADERS_SENT: Cannot write headers after they are sent to the client;修复后通过。node --test tools/test-mobile-server-streams.mjs:35/35 通过。DSHA_MOBILE_UPSTREAM_DIR=tools/mobile-plugin-upstream/lib node --test tools/test-mobile-server-patches.mjs:3/3 通过(canonical 产物、部署产物与 source map 一致)。compression@1.8.2接线隔离验证:小 JSON + Content-Length 返回 200、Content-Length: 121、正文逐字节一致;medium/large 仍由宿主 gzip 压缩。备注
dsh-web-mobile与tools/mobile-plugin-upstream.lock.json;重建时delete-session.js、index.js产物无变化。tools/run-host-tests.py --stage fast需要仓库完整输入,本机只运行了上述两个相关测试文件,其余由 CI 覆盖。