🐛 迁移测试端点从 httpbun.com 到 httpbingo.org#1617
Open
cyfung1031 wants to merge 5 commits into
Open
Conversation
httpbun.com 近期频繁 502 导致测试不稳定;httpbingo.org (https://github.com/mccutchen/httpbingo.org,由 go-httpbin 提供支持, https://github.com/mccutchen/go-httpbin) 与 httpbin/httpbun 行为高度 兼容,已逐端点用 curl 核实(/get、/post、/status、/redirect-to、 /base64、/cookies、/ip、/basic-auth、/drip 等),因此改动远小于此前 迁移到 mockhttp.org 的方案: - 域名替换:example/tests/*.js、example/crontab/crontab.js、 e2e/gm-api.spec.ts、src/app/service/service_worker/gm_api/mv3_utils.ts 中的 httpbun.com 全部替换为 httpbingo.org。 - gm_xhr_test.js 中原先依赖 httpbun 专有行为 `/status/200` 返回 `{"code": 200}` 的 "GET json" 测试battery(含 bug scriptscat#1078/scriptscat#1080 回归用例,共 11 处),httpbingo.org 的 /status/<code> 遵循标准 httpbin 语义(空响应体),改用 /get 端点校验 JSON 回显(`"method": "GET"`), 测试意图不变。 - cookies 测试改用 httpbingo.org 的查询参数式接口 (/cookies/set?name=value、/cookies/delete?name),而非 httpbun 的路径式 /cookies/set/{name}/{value}。 - POST form-encoded 测试适配 httpbingo.org 将表单值回显为数组 (Go url.Values 形状)。 - 其余测试(base64 XML/parser-error 解析、/ip、/any 的 OPTIONS、/drip 渐进式下载、/redirect-to 302 默认值、manual 模式 301 客户端回退值、 /basic-auth、任意方法 /headers、DELETE、HEAD 等)经核实与 httpbun 时代假设一致,仅替换域名。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
对照真人在 ScriptCat 与 Tampermonkey 中实际运行测试脚本的结果排查根因:
- "GET basic + headers + finalUrl"、gm_xhr_redirect_test.js 的 "GET basic
with search params" 两个用例:httpbingo.org 将查询参数与请求头回显为
数组(Go url.Values 形状,如 {"x": ["1"]}),此前断言按标量比较导致
失败;改为按数组首元素比较,与此前 POST form-encoded 用例的同类修复
保持一致。
- "onprogress fires while downloading [arraybuffer]"(仅 xhr 模式):在
ScriptCat 与 Tampermonkey 中均一致复现——原生 XMLHttpRequest 对
responseType=arraybuffer 合并 progress 事件的粒度远粗于 Fetch API 的
ReadableStream reader(用原始抓包确认 httpbingo.org /drip 端点本身在
网络层确实是渐进式下发的),因此仅 fetch 模式保留 >=4 事件的断言,
xhr 模式放宽为 >=1。
- "Redirect handling (finalUrl changes) [manual]"(仅 fetch 模式):
redirect:"manual" 在 fetch 路径下命中浏览器原生的 opaqueredirect
响应,其 headers 按 Fetch 规范固定为空——并非 httpbingo.org 特有问题,
也无法从响应本身修复。xhr 模式不走该路径,仍保留非空 responseHeaders
的断言。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
上一提交为规避 xhr 模式 onprogress 事件过少的问题,把 arraybuffer 用例 的断言从 >=4 放宽为 >=1,掩盖了问题而非解决它。改为在浏览器中直接测量 真实原因:原生 XMLHttpRequest 要等响应累积到一定字节量才会触发 onprogress(实测 ~1KB 端到端仅触发 1 次),而不是像 Fetch API 的 ReadableStream reader 那样每个到达的分片都单独上报一次。将 /drip 负载 从 1KB 提高到 2KB 后,在 Chrome 中反复实测 xhr 模式稳定产生两位数的 progress 事件,因此恢复两处用例([arraybuffer]、[stream])原有的 `>=4` 强断言,不再区分 fetch/xhr。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
对照真实浏览器再次运行的结果排查: - 两处 onprogress 用例([arraybuffer]、[stream]):既然 /drip 负载已提到 2KB,用真实 XMLHttpRequest 反复实测 xhr 模式下 event.loaded 首次即 ≥1000 字节、从未为 0(5 次重复实测均如此),因此把 lastLoaded 断言从 `fetch ? > 0 : >= 0` 收紧为统一的 `> 0`,两种模式都不再需要放宽。 - "Redirect handling (finalUrl changes) [manual]":上一提交把 xhr 模式 排除在外的假设是错的——读 src/pkg/utils/xhr/bg_gm_xhr.ts 发现 `useFetch = isFetch || !!redirect || anonymous || isBufferStream`, 只要设置了 redirect(包括 "manual"),无论测试脚本传入的是 xhr 还是 fetch 开关,底层都会强制走 Fetch API。用真实浏览器对 httpbingo.org 发起全新(no-store)请求验证:`redirect: "manual"` 下 fetch() 返回的 Response 永远是 `type: "opaqueredirect"`、`headers` 恒为 0 项,这是 Fetch 规范对 opaque 重定向响应的规定行为,并非 httpbingo.org 的问题, 也不是偶发。因此 responseHeaders 的断言只检查类型(字符串),不再要求 非空,两种模式一致。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3 tasks
Collaborator
Author
|
已使用 ScriptCat 1.5.x 和 Tampermonkey 测试 example/tests/gm_xhr_test.js |
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.
Checklist / 检查清单
背景
httpbun.com 近期频繁出现 502 错误,导致相关测试不稳定(见 #1609)。#1609 迁移到了 mockhttp.org,但 mockhttp.org 与 httpbin/httpbun 的行为差异较大(
/get用queryParams而非args/url、/post仅接受application/json、/base64以text/html提供内容、/cookies是无路径的 REST 资源、无OPTIONS路由、/drip被 Cloudflare 缓冲导致渐进式下载测试被迫放宽断言等),需要大量断言改写和用例删除才能通过。本 PR 改用 httpbingo.org(github.com/mccutchen/httpbingo.org,由 go-httpbin 提供支持)。它与经典 httpbin/httpbun 的行为高度兼容,因此改动范围远小于 #1609 的 mockhttp.org 方案,绝大多数测试断言保持原样,只替换域名。
本次改动
域名替换
example/tests/*.js、example/crontab/crontab.js、e2e/gm-api.spec.ts、src/app/service/service_worker/gm_api/mv3_utils.ts中的httpbun.com全部替换为httpbingo.org(含相关注释与日志文案)。e2e/gm-api.spec.ts覆盖的自动化用例(gm_api_sync/async_test.js、window_message_test.js等)全部跑在本地 mock server 上,不受这次域名切换影响;这几个文件里的改动只是把 mock server 用来替换@connect/URL 的正则、字符串同步更新。httpbingo.org 与 httpbun.com 的真实接口差异(3 处)
这些是本 PR 中唯一需要真正改写断言的地方,逐一用 curl / 真实浏览器核实过:
/status/<code>不再返回 JSON 体。httpbun.com 有个非标准行为:/status/200会返回{"code": 200};httpbingo.org 遵循标准 httpbin 语义,200 状态码返回空响应体。gm_xhr_test.js里依赖这个行为的 "GET json [...]" 系列用例,以及Test bug #1078/Test bug #1080回归用例(共 11 处),改用/get端点校验 JSON 回显(断言从'"code": 200'/response.code === 200改为'"method": "GET"'/response.method === "GET"),测试意图(JSON 序列化 + XML 解析路径)不变。cookies 接口形状不同。httpbun.com 用路径式接口
/cookies/set/{name}/{value}、/cookies/delete(不带参数即可清空);httpbingo.org 用查询参数式接口/cookies/set?name=value、/cookies/delete?name(必须点名要删除的 cookie)。已按新接口调整对应用例的 URL。查询参数、请求头回显、表单字段统一是数组。httpbingo.org(Go 实现)把这些字段回显为
url.Values形状的数组,例如请求/get?x=1时响应体是{"args": {"x": ["1"]}}而不是{"args": {"x": "1"}}。受影响的断言(GET basic + headers + finalUrl、gm_xhr_redirect_test.js的两个GET basic with search params用例、POST form-encoded 用例)已改为取数组首元素比较,而不是直接比较字符串。其余接口(
/base64内容类型、/redirect-to默认状态码、/ip、/any的OPTIONS、/drip渐进式下载、任意 HTTP 方法访问/headers、/post的 form/binary body 支持等)经逐一核实与 httpbun.com 时代的假设一致,测试断言未改动。真实浏览器验证暴露的 3 个问题(均已修复)
迁移完成后,人工在 ScriptCat 1.5.0-beta 与 Tampermonkey 5.5.0 中实际跑了一遍
gm_xhr_test.js(GM_xmlhttpRequest Test Harness 1.3.0,138 项 × fetch/xhr 两种模式),发现 4 类失败;逐一排查根因后确认其中 3 类是本 PR 范围内可修的测试脚本问题,1 类(见下方"已知限制")是 ScriptCat 自身的既有产品限制,超出本次迁移范围:onprogress fires while downloading [arraybuffer](xhr 模式):负载太小,原生 XHR 几乎不触发 progress。原用例用/drip?duration=2&delay=1&numbytes=1024(约 1KB)。在真实浏览器里直接测量确认:原生XMLHttpRequest要等响应累积到一定字节量才会触发onprogress,1KB 时端到端只触发 1 次;Fetch API 的ReadableStreamreader 则对每个到达的分片都单独上报,不受此限制。httpbingo.org 的/drip端点本身在网络层确实是渐进式下发的(问题出在客户端 XHR 实现,不在服务端)。把两处/drip用例([arraybuffer]、[stream])的负载从 1KB 提到 2KB 后,xhr 模式反复实测稳定产生 9~23 次 progress 事件,event.loaded首次即 ≥1000 且从未为 0——因此保留了原有progressEvents >= 4的强断言,lastLoaded断言也从fetch ? > 0 : >= 0收紧为统一的> 0,两种模式都不再需要放宽。Redirect handling (finalUrl changes) [manual]:responseHeaders断言假设有误。redirect: "manual"会让 ScriptCat 内部强制走 Fetch API——读src/pkg/utils/xhr/bg_gm_xhr.ts可确认:useFetch = isFetch || !!redirect || anonymous || isBufferStream,只要设置了redirect(不论是不是"manual"),无论测试脚本传入的 xhr/fetch 开关是什么,底层都会用 fetch()。因此 xhr、fetch 两种模式最终都会命中浏览器原生的opaqueredirect响应,其headers按 Fetch 规范固定为空。已在真实浏览器中对 httpbingo.org 发起全新(no-store)请求验证:redirect: "manual"下res.type恒为"opaqueredirect"、res.headers恒为 0 项,重复 3 次结果一致——这是浏览器 Fetch 规范的固定行为,不是偶发问题,也不是 httpbingo.org 的问题。responseHeaders断言改为只检查类型(是字符串即可),不再要求非空,两种模式一致。上述数组回显问题 —— 见上一节第 3 点,这是导致
GET basic + headers + finalUrl和gm_xhr_redirect_test.js两个用例失败的原因,已一并列在接口差异里。建议审查重点
gm_xhr_test.js中/status/200→/get(11 处)与'"code": 200'→'"method": "GET"'的替换是否保留了原测试意图。/cookies/set?name=value、/cookies/delete?name)是否与实际请求/响应行为匹配。Redirect handling [manual]的responseHeaders断言调整、/drip负载从 1KB 提到 2KB(而不是放宽断言阈值)这两处改动方向是否合理——判断依据都是上文列出的真实浏览器实测数据,而不是猜测。已知限制
redirect: "manual"下responseHeaders恒为空是浏览器 Fetch 规范对opaqueredirect响应的既有限制(只要设置了redirect,ScriptCat 就会强制走 fetch),不在本 PR 范围内修复;如需要真实重定向响应头,需要fetch_xhr.ts改走其他机制(如chrome.webRequest),作为独立产品问题跟进,不在本次迁移范围内。example/tests/gm_download_test.js未在真实浏览器中重新跑一遍(其 httpbingo.org 相关用例仅使用/bytes、/headers,均已通过 curl 核实且不涉及数组回显差异),风险较低。验证
自动化:
pnpm exec vitest run(全量单元测试)— 3370 个用例全部通过pnpm exec tsc --noEmit— 无错误pnpm exec prettier --check(改动文件)— 通过pnpm build && npx playwright test e2e/gm-api.spec.ts— 全部 7 个用例通过(sync/async GM API、WindowMessage、CSP、sandbox、inject、unwrap;这些用例走本地 mock server,未直接命中真实 httpbingo.org,但验证了域名替换未引入回归)对 httpbingo.org 端点的直接核实:
/get、/post、/status/{code}、/redirect-to、/base64/{value}、/cookies、/cookies/set、/cookies/delete、/ip、/basic-auth、/any、/drip、任意 HTTP 方法、OPTIONS、HEAD、DELETE的实际响应/drip端点在网络层确实渐进式下发字节XMLHttpRequest/fetch对/drip端点做 progress 事件计数与loaded取值实测(各配置重复 5 次):numbytes=1024时 xhr 模式仅触发 1 次onprogress;numbytes=2048时 xhr 模式稳定产生 9~23 次、event.loaded恒 > 0,fetch 模式产生数百次no-store)fetch(url, { redirect: "manual" })请求验证(重复 3 次):res.type恒为"opaqueredirect"、res.status恒为0、res.headers恒为 0 项真人在真实扩展中运行:
gm_xhr_test.js(138 项 × fetch/xhr 两种模式):首轮分别为 ✅134 ❌4(ScriptCat)与 ✅135 ❌3(Tampermonkey),4 类失败已逐项排查根因并修复(见上文"真实浏览器验证暴露的 3 个问题")gm_xhr_test.js/gm_xhr_redirect_test.js作最终确认