diff --git a/e2e/gm-api.spec.ts b/e2e/gm-api.spec.ts index 9e30f5ddc..144d30437 100644 --- a/e2e/gm-api.spec.ts +++ b/e2e/gm-api.spec.ts @@ -221,14 +221,14 @@ function patchGMApiTestCode(code: string, mockOrigin: string): string { const mockHost = new URL(mockOrigin).host; return code .replace(/^\/\/\s*@connect\s+api\.github\.com$/gm, `// @connect ${MOCK_CONNECT_HOST}`) - .replace(/^\/\/\s*@connect\s+httpbun\.com$/gm, `// @connect ${MOCK_CONNECT_HOST}`) + .replace(/^\/\/\s*@connect\s+httpbingo\.org$/gm, `// @connect ${MOCK_CONNECT_HOST}`) .replace(/https:\/\/api\.github\.com\/repos\/scriptscat\/scriptcat/g, `${mockOrigin}/repos/scriptscat/scriptcat`) - .replace(/https:\/\/httpbun\.com\/get/g, `${mockOrigin}/get`) - .replace(/https:\/\/httpbun\.com\/bytes\/64/g, `${mockOrigin}/bytes/64`) - .replace(/https:\/\/httpbun\.com\/delay\/5/g, `${mockOrigin}/delay/5`) + .replace(/https:\/\/httpbingo\.org\/get/g, `${mockOrigin}/get`) + .replace(/https:\/\/httpbingo\.org\/bytes\/64/g, `${mockOrigin}/bytes/64`) + .replace(/https:\/\/httpbingo\.org\/delay\/5/g, `${mockOrigin}/delay/5`) .replace(/https:\/\/www\.tampermonkey\.net\/favicon\.ico/g, `${mockOrigin}/favicon.ico`) .replace(/api\.github\.com\/repos\/scriptscat\/scriptcat/g, `${mockHost}/repos/scriptscat/scriptcat`) - .replace(/httpbun\.com\/get/g, `${mockHost}/get`); + .replace(/httpbingo\.org\/get/g, `${mockHost}/get`); } async function runTestScript( diff --git a/example/crontab/crontab.js b/example/crontab/crontab.js index e590eaf4b..2bccdc459 100644 --- a/example/crontab/crontab.js +++ b/example/crontab/crontab.js @@ -7,21 +7,21 @@ // @crontab */15 14-16 * * * // @grant GM_log // @grant GM_xmlhttpRequest -// @connect httpbun.com +// @connect httpbingo.org // ==/UserScript== return new Promise((resolve, reject) => { GM_log("下午两点至四点每十五分钟运行一次"); GM_xmlhttpRequest({ - url: "https://httpbun.com/get", + url: "https://httpbingo.org/get", method: "GET", responseType: "json", anonymous: true, onload(resp) { const data = resp.response; - if (resp.status !== 200 || data?.url !== "https://httpbun.com/get") { + if (resp.status !== 200 || data?.url !== "https://httpbingo.org/get") { reject("服务器回应错误。"); return; } diff --git a/example/tests/gm_api_async_test.js b/example/tests/gm_api_async_test.js index c8535935c..b51263a0f 100644 --- a/example/tests/gm_api_async_test.js +++ b/example/tests/gm_api_async_test.js @@ -24,7 +24,7 @@ // @grant unsafeWindow // @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js#sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK // @resource testCSS https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css#sha256=62f74b1cf824a89f03554c638e719594c309b4d8a627a758928c0516fa7890ab -// @connect httpbun.com +// @connect httpbingo.org // @connect example.com // @run-at document-start // ==/UserScript== @@ -192,7 +192,7 @@ return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", - url: "https://httpbun.com/get", + url: "https://httpbingo.org/get", timeout: 10000, onload: (response) => { try { @@ -200,8 +200,8 @@ assert(true, !!response.responseText, "响应内容不应为空"); const data = JSON.parse(response.responseText); assert("object", typeof data, "应该返回有效的 JSON 对象"); - assert("https://httpbun.com/get", data.url, "响应应该包含 url 字段"); - console.log("httpbun 响应信息:", data.url); + assert("https://httpbingo.org/get", data.url, "响应应该包含 url 字段"); + console.log("httpbingo 响应信息:", data.url); resolve(); } catch (error) { reject(error); @@ -220,7 +220,7 @@ await testAsync("GM.xmlHttpRequest - 返回控制对象", async () => { const controller = GM.xmlHttpRequest({ method: "GET", - url: "https://httpbun.com/get", + url: "https://httpbingo.org/get", timeout: 10000, onload: () => {}, onerror: () => {}, diff --git a/example/tests/gm_api_sync_test.js b/example/tests/gm_api_sync_test.js index 7b6008ce2..3be69512c 100644 --- a/example/tests/gm_api_sync_test.js +++ b/example/tests/gm_api_sync_test.js @@ -28,7 +28,7 @@ // @grant unsafeWindow // @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js#sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK // @resource testCSS https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css#sha256=62f74b1cf824a89f03554c638e719594c309b4d8a627a758928c0516fa7890ab -// @connect httpbun.com +// @connect httpbingo.org // @connect example.com // @run-at document-start // ==/UserScript== @@ -308,7 +308,7 @@ return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", - url: "https://httpbun.com/get", + url: "https://httpbingo.org/get", timeout: 10000, onload: (response) => { try { @@ -316,8 +316,8 @@ assert(true, !!response.responseText, "响应内容不应为空"); const data = JSON.parse(response.responseText); assert("object", typeof data, "应该返回有效的 JSON 对象"); - assert("https://httpbun.com/get", data.url, "响应应该包含 url 字段"); - console.log("httpbun 响应信息:", data.url); + assert("https://httpbingo.org/get", data.url, "响应应该包含 url 字段"); + console.log("httpbingo 响应信息:", data.url); resolve(); } catch (error) { reject(error); diff --git a/example/tests/gm_download_test.js b/example/tests/gm_download_test.js index 8814de5ca..a3df884e0 100644 --- a/example/tests/gm_download_test.js +++ b/example/tests/gm_download_test.js @@ -11,7 +11,7 @@ // @grant GM_setValue // @grant GM_getValue // @grant GM_info -// @connect httpbun.com +// @connect httpbingo.org // @connect raw.githubusercontent.com // @connect cdn.jsdelivr.net // @connect ipv4.download.thinkbroadband.com @@ -136,8 +136,8 @@ const enableTool = true; // File extends Blob; useful to verify the URL-object branch handles File too. const TEXT_FILE = new File([TEXT_BLOB], "ignored-by-api.txt", { type: "text/plain" }); - // httpbun deterministic endpoint — returns N random bytes. - const HB = "https://httpbun.com"; + // httpbingo deterministic endpoint — returns N random bytes. + const HB = "https://httpbingo.org"; // ---------- Panel ---------- const panel = h( @@ -697,7 +697,7 @@ const enableTool = true; skip(`(visual check) you should see both uniquify-target.txt and uniquify-target (1).txt`); }); - // 13) headers honored in native mode — httpbun /headers echoes request headers + // 13) headers honored in native mode — httpbingo /headers echoes request headers autoTest("headers passed to backend xhr (native mode)", async () => { // We can't easily inspect what hit the server because the response is // streamed to disk. So instead: ask /headers, which RESPONDS with the headers diff --git a/example/tests/gm_xhr_redirect_test.js b/example/tests/gm_xhr_redirect_test.js index c54682c6f..a323653b9 100644 --- a/example/tests/gm_xhr_redirect_test.js +++ b/example/tests/gm_xhr_redirect_test.js @@ -6,7 +6,7 @@ // @author you // @match *://*/*?GM_XHR_REDIRECT_TEST_SC // @grant GM_xmlhttpRequest -// @connect httpbun.com +// @connect httpbingo.org // @noframes // ==/UserScript== @@ -104,7 +104,7 @@ const enableTool = true; }); } - const HB = "https://httpbun.com"; + const HB = "https://httpbingo.org"; // ---------- Assertion utils ---------- function assertEq(a, b, msg) { @@ -131,8 +131,9 @@ const enableTool = true; async run(fetch) { const { res } = await gmRequest({ method: "GET", url: `${HB}/get?testing=234&abc=567`, responseType: "json", fetch }); assertEq(res.status, 200, "status 200"); - assertEq(res.response?.args?.testing, "234", "response ok"); - assertEq(res.response?.args?.abc, "567", "response ok"); + // httpbingo.org echoes query args as arrays (Go's url.Values shape). + assertEq(res.response?.args?.testing?.[0], "234", "response ok"); + assertEq(res.response?.args?.abc?.[0], "567", "response ok"); assertEq(res.response?.url, `${HB}/get?testing=234&abc=567`, "response ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -142,8 +143,8 @@ const enableTool = true; async run(fetch) { const { res } = await gmRequest({ method: "GET", url: `${HB}/get?abc=567&testing=234`, responseType: "json", fetch }); assertEq(res.status, 200, "status 200"); - assertEq(res.response?.args?.testing, "234", "response ok"); - assertEq(res.response?.args?.abc, "567", "response ok"); + assertEq(res.response?.args?.testing?.[0], "234", "response ok"); + assertEq(res.response?.args?.abc?.[0], "567", "response ok"); assertEq(res.response?.url, `${HB}/get?abc=567&testing=234`, "response ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, diff --git a/example/tests/gm_xhr_test.js b/example/tests/gm_xhr_test.js index 2cccdf56a..2e0e1f89c 100644 --- a/example/tests/gm_xhr_test.js +++ b/example/tests/gm_xhr_test.js @@ -6,7 +6,7 @@ // @author you // @match *://*/*?GM_XHR_TEST_SC // @grant GM_xmlhttpRequest -// @connect httpbun.com +// @connect httpbingo.org // @connect nonexistent-domain-abcxyz.test // @connect raw.githubusercontent.com // @connect translate.googleapis.com @@ -21,8 +21,9 @@ - Uses httpbin.org endpoints for deterministic echo/response behavior. - Prints a summary and a detailed per-test log with assertions. - NOTE: Endpoints now point to https://httpbun.com (a faster httpbin-like service). - See https://httpbun.com for docs and exact paths. (Also supports /get, /post, /bytes/{n}, /delay/{s}, /status/{code}, /redirect-to, /headers, /any, etc.) + NOTE: Endpoints now point to https://httpbingo.org (open source, https://github.com/mccutchen/httpbingo.org, + backed by https://github.com/mccutchen/go-httpbin — httpbin-compatible). + See https://httpbingo.org for docs and exact paths. (Also supports /get, /post, /bytes/{n}, /delay/{s}, /status/{code}, /redirect-to, /headers, /any, etc.) */ /* @@ -439,13 +440,13 @@ const enableTool = true; }); } - // Switched base host from httpbin to httpbun (faster). - // See: https://httpbun.com (endpoints: /get, /post, /bytes/{n}, /delay/{s}, /status/{code}, /redirect-to, /headers, /any, etc.) - const HB = "https://httpbun.com"; + // Switched base host to httpbingo.org (open source, go-httpbin-backed, httpbin-compatible). + // See: https://httpbingo.org (endpoints: /get, /post, /bytes/{n}, /delay/{s}, /status/{code}, /redirect-to, /headers, /any, etc.) + const HB = "https://httpbingo.org"; - // Helper: handle minor schema diffs between httpbin/httpbun for query echo + // Helper: handle minor schema diffs across httpbin-family servers for query echo function getQueryObj(body) { - // httpbin uses "args", httpbun may use "query" (and still often provides "args" for compatibility). + // httpbin/httpbingo use "args" (and some httpbin-likes use "query" for compatibility). return body.args || body.query || body.params || {}; } @@ -595,15 +596,15 @@ const enableTool = true; { name: "GET json [responseType: undefined]", async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); - assertEq(`${res.response}`.includes('"code": 200'), true, "response ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); + assertEq(`${res.response}`.includes('"method": "GET"'), true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -611,7 +612,7 @@ const enableTool = true; { name: 'GET json [responseType: ""]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -619,8 +620,8 @@ const enableTool = true; fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); - assertEq(`${res.response}`.includes('"code": 200'), true, "response ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); + assertEq(`${res.response}`.includes('"method": "GET"'), true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -628,7 +629,7 @@ const enableTool = true; { name: 'GET json [responseType: "text"]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -636,8 +637,8 @@ const enableTool = true; fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); - assertEq(`${res.response}`.includes('"code": 200'), true, "response ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); + assertEq(`${res.response}`.includes('"method": "GET"'), true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -645,7 +646,7 @@ const enableTool = true; { name: 'GET json [responseType: "json"]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -653,8 +654,8 @@ const enableTool = true; fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); - assertEq(typeof res.response === "object" && res.response?.code === 200, true, "response ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); + assertEq(typeof res.response === "object" && res.response?.method === "GET", true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -662,7 +663,7 @@ const enableTool = true; { name: 'GET json [responseType: "document"]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -670,7 +671,7 @@ const enableTool = true; fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); assertEq(res.response instanceof XMLDocument, true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); @@ -679,7 +680,7 @@ const enableTool = true; { name: 'GET json [responseType: "stream"]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -696,7 +697,7 @@ const enableTool = true; { name: 'GET json [responseType: "arraybuffer"]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -704,7 +705,7 @@ const enableTool = true; fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); assertEq(res.response instanceof ArrayBuffer, true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); @@ -713,7 +714,7 @@ const enableTool = true; { name: 'GET json [responseType: "blob"]', async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -721,7 +722,7 @@ const enableTool = true; fetch, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); assertEq(res.response instanceof Blob, true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); @@ -874,10 +875,12 @@ const enableTool = true; }); const body = JSON.parse(res.responseText); assertEq(res.status, 200, "status 200"); + // httpbingo.org echoes query args and headers as arrays (Go's url.Values shape). const q = getQueryObj(body); - assertEq(q.x, "1", "query args"); + assertEq(q.x?.[0] ?? q.x, "1", "query args"); const hdrs = body.headers || {}; - assertEq(hdrs["X-Custom"] || hdrs["x-custom"], "Hello", "custom header echo"); + const customHeader = hdrs["X-Custom"] || hdrs["x-custom"]; + assertEq(Array.isArray(customHeader) ? customHeader[0] : customHeader, "Hello", "custom header echo"); assertEq(res.finalUrl, url, "finalUrl matches"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -957,7 +960,14 @@ const enableTool = true; ]); assertEq(res?.status, 301, "status is 301"); assertEq(res?.finalUrl, url, "finalUrl is original url"); - assertEq(typeof res?.responseHeaders === "string" && res?.responseHeaders !== "", true, "responseHeaders ok"); + // Any `redirect` option (including "manual") makes the manager use the Fetch API + // internally regardless of the xhr/fetch toggle here, so both modes hit the browser's + // native opaqueredirect Response - whose headers are empty by spec (Fetch spec + // §opaque-redirect filtered response), confirmed directly against httpbingo.org with a + // fresh (no-store) fetch(): res.type === "opaqueredirect", res.headers has 0 entries, + // every time. This is a manager/browser limitation, not an httpbingo.org gap, so only + // check the type here rather than requiring a non-empty value. + assertEq(typeof res?.responseHeaders === "string", true, "responseHeaders ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, }, @@ -974,8 +984,9 @@ const enableTool = true; }); const body = JSON.parse(res.responseText); assertEq(res.status, 200); - assertEq((body.form || {}).a, "1", "form a"); - assertEq((body.form || {}).b, "two", "form b"); + // httpbingo.org echoes form values as arrays (Go's url.Values shape). + assertEq((body.form?.a || [])[0], "1", "form a"); + assertEq((body.form?.b || [])[0], "two", "form b"); assertEq(objectProps(res), "ok", "Object Props OK"); }, }, @@ -1039,7 +1050,7 @@ const enableTool = true; async run(fetch) { let progressCounter = 0; const size = 40; // MAX 90 - // httpbun doesn't have /image/png; use /bytes to ensure blob download + // httpbingo doesn't have /image/png; use /bytes to ensure blob download const { res } = await gmRequest({ method: "GET", url: `${HB}/bytes/${size}`, @@ -1055,7 +1066,7 @@ const enableTool = true; assertEq(buf.byteLength, size, "byte length matches"); assert(progressCounter >= 1, "progressCounter >= 1"); assertEq(objectProps(res), "ok", "Object Props OK"); - // Do not assert image MIME; httpbun returns octet-stream here. + // Do not assert image MIME; httpbingo returns octet-stream here. }, }, { @@ -1221,7 +1232,12 @@ const enableTool = true; const start = performance.now(); GM_xmlhttpRequest({ method: "GET", - url: `${HB}/drip?duration=2&delay=1&numbytes=1024`, // ~1KB + // Native XMLHttpRequest only surfaces onprogress once the response has accumulated + // enough bytes to cross its internal flush threshold (~1KB was observed to fire only + // once end-to-end in real Chrome; 2KB reliably produced dozens of events across + // repeated runs), unlike the Fetch API's ReadableStream reader, which reports every + // chunk as it arrives regardless of size. Use 2KB so both modes clear the >=4 bar. + url: `${HB}/drip?duration=2&delay=1&numbytes=2048`, // ~2KB responseType: "arraybuffer", onprogress: (ev) => { progressEvents++; @@ -1237,8 +1253,7 @@ const enableTool = true; }); assertEq(res.status, 200); assert(progressEvents >= 4, "received at least 4 progress events"); - // `progress` is guaranteed to fire only in the Fetch API. - assert(fetch ? lastLoaded > 0 : lastLoaded >= 0, "progress loaded captured"); + assert(lastLoaded > 0, "progress loaded captured"); assert(!response, "no response"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -1254,7 +1269,7 @@ const enableTool = true; const start = performance.now(); GM_xmlhttpRequest({ method: "GET", - url: `${HB}/drip?duration=2&delay=1&numbytes=1024`, // ~1KB + url: `${HB}/drip?duration=2&delay=1&numbytes=2048`, // ~2KB, see sibling [arraybuffer] test above responseType: "stream", onloadstart: async (ev) => { const reader = ev.response?.getReader(); @@ -1281,8 +1296,7 @@ const enableTool = true; }); assertEq(res.status, 200); assert(progressEvents >= 4, "received at least 4 progress events"); - // `progress` is guaranteed to fire only in the Fetch API. - assert(fetch ? lastLoaded > 0 : lastLoaded >= 0, "progress loaded captured"); + assert(lastLoaded > 0, "progress loaded captured"); assert(response instanceof ReadableStream && typeof response.getReader === "function", "response"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -1323,7 +1337,7 @@ const enableTool = true; url: `${HB}/any`, fetch, }); - // httpbun commonly returns 200 for OPTIONS + // httpbingo commonly returns 200 for OPTIONS assert(res.status === 200 || res.status === 204, "200/204 on OPTIONS"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -1348,7 +1362,7 @@ const enableTool = true; // httpbin echoes Cookie header in headers const { res } = await gmRequest({ method: "GET", - url: `${HB}/cookies/set/abc/123`, + url: `${HB}/cookies/set?abc=123`, fetch, }); }, @@ -1406,7 +1420,7 @@ const enableTool = true; // httpbin echoes Cookie header in headers const { res } = await gmRequest({ method: "GET", - url: `${HB}/cookies/delete`, + url: `${HB}/cookies/delete?abc`, anonymous: true, fetch, }); @@ -1418,7 +1432,7 @@ const enableTool = true; // httpbin echoes Cookie header in headers const { res } = await gmRequest({ method: "GET", - url: `${HB}/cookies/set/def/456`, + url: `${HB}/cookies/set?def=456`, anonymous: true, fetch, }); @@ -1446,7 +1460,7 @@ const enableTool = true; // httpbin echoes Cookie header in headers const { res } = await gmRequest({ method: "GET", - url: `${HB}/cookies/delete`, + url: `${HB}/cookies/delete?def`, anonymous: true, fetch, }); @@ -1487,7 +1501,7 @@ const enableTool = true; { name: "Invalid method -> expected server 405 or 200 echo", async run(fetch) { - // httpbun accepts any method on /headers (per docs), so status may be 200 + // httpbingo accepts any method on /headers (per docs), so status may be 200 const { res } = await gmRequest({ method: "FOOBAR", url: `${HB}/headers`, @@ -1603,7 +1617,7 @@ const enableTool = true; { name: "Test bug #1078", async run(fetch) { - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -1612,8 +1626,8 @@ const enableTool = true; onprogress() {}, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); - assertEq(typeof res.response === "object" && res.response?.code === 200, true, "response ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); + assertEq(typeof res.response === "object" && res.response?.method === "GET", true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertEq(objectProps(res), "ok", "Object Props OK"); }, @@ -1622,7 +1636,7 @@ const enableTool = true; name: "Test bug #1080", async run(fetch) { const readyStateList = []; - const url = `${HB}/status/200`; + const url = `${HB}/get`; const { res } = await gmRequest({ method: "GET", url, @@ -1633,8 +1647,8 @@ const enableTool = true; }, }); assertEq(res.status, 200, "status 200"); - assertEq(`${res.responseText}`.includes('"code": 200'), true, "responseText ok"); - assertEq(typeof res.response === "object" && res.response?.code === 200, true, "response ok"); + assertEq(`${res.responseText}`.includes('"method": "GET"'), true, "responseText ok"); + assertEq(typeof res.response === "object" && res.response?.method === "GET", true, "response ok"); assertEq(res.responseXML instanceof XMLDocument, true, "responseXML ok"); assertDeepEq(readyStateList, fetch ? [2, 4] : [1, 2, 3, 4], "status 200"); assertEq(objectProps(res), "ok", "Object Props OK"); diff --git a/example/tests/window_message_test.js b/example/tests/window_message_test.js index 444e21179..4e7fdbf8b 100644 --- a/example/tests/window_message_test.js +++ b/example/tests/window_message_test.js @@ -9,7 +9,7 @@ // @grant GM_xmlhttpRequest // @grant GM.setClipboard // @grant unsafeWindow -// @connect httpbun.com +// @connect httpbingo.org // @run-at document-end // @noframes // ==/UserScript== @@ -94,14 +94,14 @@ const response = await withTimeout( GM.xmlHttpRequest({ method: "GET", - url: `https://httpbun.com/get?marker=${encodeURIComponent(marker)}`, + url: `https://httpbingo.org/get?marker=${encodeURIComponent(marker)}`, responseType: "json", }), "GM.xmlHttpRequest", ); assertSame(200, response.status, "status should be 200"); - assertTrue(response.finalUrl.includes("httpbun.com/get"), "finalUrl should be populated"); + assertTrue(response.finalUrl.includes("httpbingo.org/get"), "finalUrl should be populated"); assertTrue(typeof response.responseHeaders === "string", "responseHeaders should be a string"); assertTrue(response.response && typeof response.response === "object", "JSON response should be parsed"); @@ -119,7 +119,7 @@ new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", - url: "https://httpbun.com/bytes/64", + url: "https://httpbingo.org/bytes/64", onreadystatechange: (res) => { states.push(res.readyState); }, @@ -142,7 +142,7 @@ new Promise((resolve, reject) => { const request = GM_xmlhttpRequest({ method: "GET", - url: "https://httpbun.com/delay/5", + url: "https://httpbingo.org/delay/5", onload: () => reject(new Error("request loaded before abort")), onerror: reject, ontimeout: reject, diff --git a/src/app/service/service_worker/gm_api/mv3_utils.ts b/src/app/service/service_worker/gm_api/mv3_utils.ts index a545f4e85..b2d387930 100644 --- a/src/app/service/service_worker/gm_api/mv3_utils.ts +++ b/src/app/service/service_worker/gm_api/mv3_utils.ts @@ -14,8 +14,8 @@ type TbgMarkerMapEntry = { const bgMarkerMap = new Map(); export const normalizeBackgroundRequestUrl = (url: string) => { const u = new URL(url); - // input "https://user:passwd@httpbun.com/basic-auth/user/passwd?q=1&r=2" - // output "https://httpbun.com/basic-auth/user/passwd?q=1&r=2" + // input "https://user:passwd@httpbingo.org/basic-auth/user/passwd?q=1&r=2" + // output "https://httpbingo.org/basic-auth/user/passwd?q=1&r=2" return `${u.origin}${u.pathname}${u.search}`; }; diff --git a/tests/example/crontab.test.ts b/tests/example/crontab.test.ts index 2853841f0..995b182b1 100644 --- a/tests/example/crontab.test.ts +++ b/tests/example/crontab.test.ts @@ -14,23 +14,23 @@ const runExample = new Function("GM_log", "GM_xmlhttpRequest", source) as ( ) => Promise; describe("定时脚本示例", () => { - it("定时请求 httpbun 并记录响应 URL", async () => { + it("定时请求 httpbingo 并记录响应 URL", async () => { const log = vi.fn(); let requestDetails: RequestDetails | undefined; const result = runExample(log, (details) => { requestDetails = details; }); - expect(requestDetails?.url).toBe("https://httpbun.com/get"); + expect(requestDetails?.url).toBe("https://httpbingo.org/get"); requestDetails?.onload({ status: 200, response: { - url: "https://httpbun.com/get", + url: "https://httpbingo.org/get", }, }); await expect(result).resolves.toBeUndefined(); - expect(log).toHaveBeenCalledWith("定时请求成功:\nhttps://httpbun.com/get"); + expect(log).toHaveBeenCalledWith("定时请求成功:\nhttps://httpbingo.org/get"); }); });