Skip to content

🐛 迁移测试端点从 httpbun.com 到 mockhttp.org#1609

Draft
cyfung1031 wants to merge 6 commits into
scriptscat:mainfrom
cyfung1031:claude/migrate-httpbun-mockhttp-1341f6
Draft

🐛 迁移测试端点从 httpbun.com 到 mockhttp.org#1609
cyfung1031 wants to merge 6 commits into
scriptscat:mainfrom
cyfung1031:claude/migrate-httpbun-mockhttp-1341f6

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes mentioned issues / 已修复或实现
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

背景

httpbun.com 近期频繁出现 502 错误,导致相关测试不稳定。改用开源、可自托管的 mockhttp.org(更稳定)。mockhttp.org 并非 httpbun/httpbin 的行为复刻,实测发现两者在多个端点上的响应结构、状态码、内容协商等方面存在真实差异——本 PR 不是单纯替换域名字符串,而是对每一处差异逐一核实(curl / 原始 TLS socket 抓包 / 实际浏览器运行测试脚本)并相应调整断言。

本次改动

域名替换example/tests/*.jsexample/crontab/crontab.jse2e/gm-api.spec.tssrc/app/service/service_worker/gm_api/mv3_utils.ts 中的 httpbun.com 全部替换为 mockhttp.orge2e/gm-api.spec.ts 中用于替换 @connect/URL 的正则同步更新;本地 mock server 的 /get 响应新增 method 字段,以配合 sync/async GM API 测试新增的 finalUrl/method 断言。

响应结构差异适配

  • /get 返回 queryParams 字段而非 httpbin 风格的 url/args,相关测试改用 finalUrl(XHR 框架自带字段)或 queryParams 校验。
  • /status/:code 响应体格式不同({"status":"..."} 而非 httpbin 风格的 {"code":...}),已同步调整字符串匹配。
  • /base64/:valueContent-Type: text/html 提供内容(httpbun 并非如此),GM_xhr 按自身 MIME 类型表(docParseTypes,见 src/app/service/content/gm_api/gm_xhr.ts)正确地以 HTML 模式解析 responseXML,得到 HTMLDocument 而非 XMLDocument——涉及的 7 项 GET basic [responseType: *] 断言已从 instanceof XMLDocument 改为 instanceof Document
  • responseType=document(parser error) 用例原依赖 XML 解析失败产生 <parsererror> 元素,但 HTML 解析模式永远不会产生该元素;已重写为验证二进制垃圾数据以 HTML 模式解析不会抛出异常,而非依赖已不可复现的解析错误路径。
  • /redirect-to 默认返回 302(而非 httpbun 的 301);重定向后续 [default]/[follow] 用例此前只校验 finalUrl,未校验响应体内容——已补充校验重定向目标的响应体 method/queryParams,确保验证的是"服务端确实返回了正确响应"而非仅"客户端认为自己跟随了重定向"。
  • /cookies 是单一 REST 资源(POST 设置、GET 读取、DELETE?name= 清除单个),而非 httpbin 风格的 /cookies/set/{name}/{value} 路径式接口。初版误判该端点为无状态桩并整体移除了相关测试,后经 curl 逐步验证真实的 Set-Cookie/Cookie 往返行为后,按正确的接口形状恢复了完整的匿名 cookie 测试集群。
  • /post 仅接受 application/json 请求体(表单编码/二进制请求体会返回 415),已移除无法在新端点验证的用例并注明原因(对应 mockhttp 侧的修复见下方"关联")。
  • 全站无 OPTIONS 路由(统一 404),自定义 HTTP 方法会在边缘节点返回 502,已放宽相应断言的预期状态码集合。

根据实际浏览器运行结果修复(用户执行 gm_xhr_test.js v1.3.0 后反馈 112 通过 / 22 失败,逐项排查根因):

  • Redirect handling [manual]:更正了此前的错误判断——这并非 mockhttp 302 vs httpbun 301 的服务端差异,而是 ScriptCat/Tampermonkey 自身的已知行为:redirect: "manual" 会走 fetch 路径,Fetch 规范使 opaqueredirect 响应的真实状态码不可从 JS 读取,管理器通常会硬编码一个回退状态码(常见为 301)而非服务器真实返回值(已用 curl 反复确认 mockhttp.org 该端点始终返回 302,但 GM_xmlhttpRequest 仍报告 301)。断言改回 301 并补充准确注释;相关表述已泛化,避免点名具体管理器或内部实现路径(该测试脚本本身可在 ScriptCat 或 Tampermonkey 下运行)。
  • onprogress fires while downloading [stream]/[arraybuffer]:用原始 TLS socket 抓包确认 mockhttp.org(经 Cloudflare 代理)会把整个响应体在服务端缓冲后一次性下发,不会按 /drip 参数真正分批下发字节,因此 onprogress 不可能触发 4 次以上。断言从 >=4 放宽为 >=1 并在注释中记录抓包证据。

已知限制

  • onprogress 断言目前为 >=1(而非原先针对 httpbun 的 >=4),因为 mockhttp.org 的公共实例(Cloudflare + Google Cloud Run)会缓冲整个响应体后一次性下发,与 /drip 声明的分批下发时长无关。已向 mockhttp 提交 jaredwray/mockhttp#164 增加 unbuffered 参数尝试绕过代理缓冲;该 PR 尚未合并/部署,即便合并后也需要该仓库测试脚本改用该参数才能恢复 >=4 断言,本 PR 暂不依赖其结果。
  • 表单编码 POST、二进制 POST body 相关测试用例已移除(保留说明性注释),因为 mockhttp.org 当前对非 application/json 请求体统一返回 415。已提交 jaredwray/mockhttp#161(表单编码支持)与 #163(原始/二进制 body 支持),均尚未合并;一旦合并部署,可考虑恢复这些用例。
  • OPTIONS request 测试当前预期 404(/anythingOPTIONS 路由)。已提交 jaredwray/mockhttp#162/anything 增加 OPTIONS 支持,尚未合并;合并部署后需将该断言改回 200,否则会转为失败。
  • Redirect handling [manual] 断言的是 ScriptCat/Tampermonkey 自身对 redirect: "manual" 的已知回退行为(固定报告 301),而非 mockhttp.org 的真实状态码;这是一个独立于本次迁移的产品行为,已作为后续任务跟进(fetch_xhr.ts 是否可通过 chrome.webRequest 拿到真实状态码),不在本 PR 范围内修复。
  • example/tests/gm_xhr_test.jsgm_xhr_redirect_test.js 属于手动验证脚本(docs/verification.md 工作流),不在自动化 CI(e2e/gm-api.spec.ts)覆盖范围内——CI 覆盖的 gm_api_sync_test.js/gm_api_async_test.js/window_message_test.js 均通过本地 mock server 运行,不受 mockhttp.org 真实端点行为影响。

建议审查重点

  • example/tests/gm_xhr_test.jsresponseXML/responseinstanceof XMLDocument 改为 instanceof Document 的 7 处改动,是否符合预期(docParseTypes 判定逻辑见 src/app/service/content/gm_api/gm_xhr.ts:121-129,374-393)。
  • Redirect handling [manual] 断言维持 301 而非 302 的注释是否清晰易懂——这是在验证管理器自身的已知回退值,而非服务器真实状态码。
  • 移除的表单编码/二进制 body 测试用例、cookie 测试集群的恢复方式,是否符合 "只做当前端点能验证的事" 的取舍。

关联

配合本次迁移,已向 jaredwray/mockhttp 提交以下上游 PR(均为独立问题,未合并;不影响本 PR 的可合并性):

  • #160 /base64/:value 路径参数超过约 100 字符时静默 404(find-my-way 默认 maxParamLength
  • #161 /post/anything 支持 application/x-www-form-urlencoded 请求体
  • #162 /anything 支持 OPTIONS 方法
  • #163 /post/anything 支持原始/二进制请求体
  • #164 /drip 增加 unbuffered 参数,尝试绕过反向代理缓冲

验证

  • pnpm exec vitest run tests/example/crontab.test.ts — 通过
  • pnpm exec tsc --noEmit — 无相关错误
  • pnpm exec eslint / pnpm exec prettier --check — 无相关错误
  • pnpm build && npx playwright test e2e/gm-api.spec.ts — 全部 7 个用例通过(sync/async GM API、WindowMessage、CSP、sandbox、inject、unwrap)
  • 对 mockhttp.org 各端点(/get/post/anything/bytes/delay/status/redirect-to/basic-auth/headers/ip/cookies/drip/base64)逐一 curl 及原始 TLS socket 抓包验证实际行为,确认迁移后测试脚本的断言与真实响应一致
  • 由用户在真实浏览器扩展中实际执行 gm_xhr_test.js v1.3.0(example/tests/),首次运行反馈 ✅112 ❌22;后续针对 22 处失败逐项排查根因并修复,均已通过对照 mockhttp.org 真实响应验证,但修复后未再次于浏览器中完整重跑该手动测试脚本进行最终确认

cyfung1031 and others added 4 commits July 18, 2026 06:54
httpbun.com 近期频繁出现 502 错误导致测试不稳定;mockhttp.org
(https://github.com/jaredwray/mockhttp) 开源且更稳定。除替换域名外,
mockhttp.org 的响应结构与 httpbun 存在差异(如 /get 用 queryParams 而非
url/args 字段、/post 仅接受 application/json、/redirect-to 默认返回 302
而非 301、/cookies 为无状态桩、无 OPTIONS 路由),已同步调整相关断言;
无法在新端点上验证的用例(cookie 往返、form/binary body 上传)已移除并
注明原因。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mockhttp.org 的 /cookies 是单一 REST 资源(POST 设置、GET 读取、
DELETE?name= 清除单个),而不是 httpbin/httpbun 风格的
/cookies/set/{name}/{value}、/cookies/delete 路径式接口;此前误判为
"无状态桩" 并整体移除了相关测试。经 curl 逐步验证真实的 Set-Cookie/
Cookie 往返行为后,按正确的接口形状恢复该测试集群。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
实测发现 mockhttp.org 的 /base64/{value} 路由对超过约 100 字符的路径
参数返回 404(未在其 OpenAPI 文档中说明的隐藏限制),而原先沿用 httpbun
时代的 encodedBase64 常量长达 460 字符,导致全部 8 个 "GET basic
[responseType: ...]" 用例在新端点下实际会 404 失败。换用一个编码后仅
76 字符的等价短句,并通过 curl 直接请求真实服务确认解码结果一致。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
gm_xhr_test.js 与 gm_xhr_redirect_test.js 中 "Redirect handling
(finalUrl changes) [default]"/"[follow]" 两个用例此前只校验
status===200 与 finalUrl===target,未校验响应体内容——finalUrl 只能
证明客户端认为自己跟随了重定向,无法证明服务端确实返回了 /get 的正确
响应(而非恰好也是 200 的缓存/错误响应)。现补充校验响应体中
method==="GET" 且 queryParams 与重定向目标的查询参数一致,并已对照
真实 mockhttp.org 服务器验证通过。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cyfung1031
cyfung1031 marked this pull request as draft July 17, 2026 23:32
@cyfung1031

Copy link
Copy Markdown
Collaborator Author

mockhttp.org 是跑得很快但 API 不齐全。我已经提交了 PR,先把这个设为DRAFT,日后再处理

cyfung1031 and others added 2 commits July 18, 2026 08:39
对照真实浏览器扩展运行的测试结果,逐项排查根因并修复(均已用 curl/
原始 socket 抓包对照真实 mockhttp.org 行为验证):

- "GET basic [responseType: *]"(7 项 × fetch/xhr):mockhttp.org 的
  /base64 以 Content-Type: text/html 提供响应(httpbun 并非如此),
  GM_xhr 按其自身 MIME 类型表(src/app/service/content/gm_api/gm_xhr.ts
  的 docParseTypes)正确地以 HTML 模式解析 responseXML,得到
  HTMLDocument 而非 XMLDocument——两者都是 Document 的子类,断言改为
  `instanceof Document` 而非 `instanceof XMLDocument`。

- "responseType=document(parser error)":HTML 解析模式永远不会产生
  <parsererror>(这是 XML 模式特有的错误恢复机制),而 mockhttp.org
  的 /base64 固定以 text/html 提供内容,导致该用例原有前提在新端点下
  不可复现。已重写为验证二进制垃圾数据以 HTML 模式解析不会抛出异常
  (仍有意义的回归覆盖),而非依赖不可能出现的解析错误元素。

- "Redirect handling (finalUrl changes) [manual]":更正之前的错误判断
  ——这不是 mockhttp.org 302 vs httpbun 301 的差异,而是 ScriptCat 自身
  的已知行为:redirect:"manual" 会走 fetch 路径,Fetch 规范使
  opaqueredirect 响应的真实状态码不可读,src/pkg/utils/xhr/fetch_xhr.ts
  硬编码回退为 301,与服务器真实返回值无关(已用 curl 反复确认
  mockhttp.org 该端点始终返回 302,但 GM_xhr 仍报告 301)。断言改回
  301 并补充准确注释;已作为独立产品缺陷创建后续任务跟进
  (fetch_xhr.ts 是否可通过 webRequest 拿到真实状态码)。

- "onprogress fires while downloading [stream]/[arraybuffer]":用原始
  socket 抓包确认 mockhttp.org(经 Cloudflare 代理)会把整个响应体在
  服务端缓冲后一次性下发,不会按 /drip 参数真正分批下发字节,因此
  onprogress 不可能触发 4 次以上。断言从 >=4 放宽为 >=1 并补充说明。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
该测试脚本本身是通用的 GM_xmlhttpRequest 测试工具,可在 ScriptCat 或
Tampermonkey 下运行(脚本头部未使用任何 ScriptCat 专属 API)。此前为
[manual] 重定向状态码断言添加的注释误将其表述为"ScriptCat 的已知回退
行为"并点名 ScriptCat 内部源码路径(src/pkg/utils/xhr/fetch_xhr.ts)
——这在 Tampermonkey 环境下阅读会造成困惑(该路径根本不存在于
Tampermonkey 中)。改为泛化表述为"任何以此方式实现 manual 重定向的
管理器",不再点名具体扩展或内部实现路径。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant