-
Notifications
You must be signed in to change notification settings - Fork 3.9k
fix(http): disable keep-alive on proxy authentication failure (407) #25884
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { afterAll, beforeAll, expect, it } from "bun:test"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { afterAll, beforeAll, describe, expect, it } from "bun:test"; | ||||||||||||||||||||||||||||||||||||||||||||
| import fs from "fs"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { bunEnv, bunExe, gc } from "harness"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { tmpdir } from "os"; | ||||||||||||||||||||||||||||||||||||||||||||
| import path from "path"; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| let proxy, auth_proxy, server; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,145 +76,185 @@ afterAll(() => { | |||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const test = process.env.PROXY_URL ? it : it.skip; | ||||||||||||||||||||||||||||||||||||||||||||
| describe.concurrent(() => { | ||||||||||||||||||||||||||||||||||||||||||||
| test("should be able to post on TLS", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const data = JSON.stringify({ | ||||||||||||||||||||||||||||||||||||||||||||
| "name": "bun", | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| test("should be able to post on TLS", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const data = JSON.stringify({ | ||||||||||||||||||||||||||||||||||||||||||||
| "name": "bun", | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| const result = await fetch("https://httpbin.org/post", { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: process.env.PROXY_URL, | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| body: data, | ||||||||||||||||||||||||||||||||||||||||||||
| }).then(res => res.json()); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const result = await fetch("https://httpbin.org/post", { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: process.env.PROXY_URL, | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| body: data, | ||||||||||||||||||||||||||||||||||||||||||||
| }).then(res => res.json()); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(result.data).toBe(data); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| expect(result.data).toBe(data); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| test("should be able to post bigger on TLS", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const data = fs.readFileSync(path.join(import.meta.dir, "fetch.json")).toString("utf8"); | ||||||||||||||||||||||||||||||||||||||||||||
| const result = await fetch("https://httpbin.org/post", { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: process.env.PROXY_URL, | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| body: data, | ||||||||||||||||||||||||||||||||||||||||||||
| }).then(res => res.json()); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(result.data).toBe(data); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| test("should be able to post bigger on TLS", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const data = fs.readFileSync(path.join(import.meta.dir, "fetch.json")).toString("utf8"); | ||||||||||||||||||||||||||||||||||||||||||||
| const result = await fetch("https://httpbin.org/post", { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: process.env.PROXY_URL, | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| body: data, | ||||||||||||||||||||||||||||||||||||||||||||
| }).then(res => res.json()); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(result.data).toBe(data); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| describe("proxy non-TLS", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| let url; | ||||||||||||||||||||||||||||||||||||||||||||
| let auth_proxy_url; | ||||||||||||||||||||||||||||||||||||||||||||
| let proxy_url; | ||||||||||||||||||||||||||||||||||||||||||||
| const requests = [ | ||||||||||||||||||||||||||||||||||||||||||||
| () => [new Request(url), auth_proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| () => [ | ||||||||||||||||||||||||||||||||||||||||||||
| new Request(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| body: "Hello, World", | ||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||
| auth_proxy_url, | ||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||
| () => [url, auth_proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| () => [new Request(url), proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| () => [ | ||||||||||||||||||||||||||||||||||||||||||||
| new Request(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| body: "Hello, World", | ||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||
| proxy_url, | ||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||
| () => [url, proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||
| beforeAll(() => { | ||||||||||||||||||||||||||||||||||||||||||||
| url = `http://localhost:${server.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| auth_proxy_url = `http://squid_user:ASD123%40123asd@localhost:${auth_proxy.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| proxy_url = `localhost:${proxy.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| it("proxy non-TLS", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const url = `http://localhost:${server.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| const auth_proxy_url = `http://squid_user:ASD123%40123asd@localhost:${auth_proxy.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| const proxy_url = `localhost:${proxy.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| const requests = [ | ||||||||||||||||||||||||||||||||||||||||||||
| [new Request(url), auth_proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||||
| new Request(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| body: "Hello, World", | ||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||
| auth_proxy_url, | ||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||
| [url, auth_proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| [new Request(url), proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||||
| new Request(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||
| body: "Hello, World", | ||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||
| proxy_url, | ||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||
| [url, proxy_url], | ||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||
| for (let [request, proxy] of requests) { | ||||||||||||||||||||||||||||||||||||||||||||
| gc(); | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(request, { verbose: true, proxy }); | ||||||||||||||||||||||||||||||||||||||||||||
| gc(); | ||||||||||||||||||||||||||||||||||||||||||||
| const text = await response.text(); | ||||||||||||||||||||||||||||||||||||||||||||
| gc(); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(text).toBe("Hello, World"); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| for (let callback of requests) { | ||||||||||||||||||||||||||||||||||||||||||||
| test(async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const [request, proxy] = callback(); | ||||||||||||||||||||||||||||||||||||||||||||
| gc(); | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(request, { verbose: true, proxy }); | ||||||||||||||||||||||||||||||||||||||||||||
| gc(); | ||||||||||||||||||||||||||||||||||||||||||||
| const text = await response.text(); | ||||||||||||||||||||||||||||||||||||||||||||
| gc(); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(text).toBe("Hello, World"); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+143
to
+152
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Add descriptive test names for better debugging. The tests in this loop lack descriptive names, making it difficult to identify which request configuration fails when debugging. ♻️ Suggested improvementConsider adding descriptive test names based on the request configuration: - for (let callback of requests) {
- test(async () => {
+ for (let i = 0; i < requests.length; i++) {
+ test(`proxy request configuration ${i + 1}/${requests.length}`, async () => {
- const [request, proxy] = callback();
+ const [request, proxy] = requests[i]();
gc();
const response = await fetch(request, { verbose: true, proxy });
gc();Or better yet, use 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| it("proxy non-TLS auth can fail", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const url = `http://localhost:${server.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| it("proxy non-TLS auth can fail", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const url = `http://localhost:${server.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(url, { verbose: true, proxy: `http://localhost:${auth_proxy.port}` }); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(response.status).toBe(407); | ||||||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||
| expect(true).toBeFalsy(); | ||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: `http://localhost:${auth_proxy.port}`, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(response.status).toBe(407); | ||||||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||
| expect(true).toBeFalsy(); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: `http://squid_user:asdf123@localhost:${auth_proxy.port}`, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(response.status).toBe(403); | ||||||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||
| expect(true).toBeFalsy(); | ||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(url, { | ||||||||||||||||||||||||||||||||||||||||||||
| verbose: true, | ||||||||||||||||||||||||||||||||||||||||||||
| proxy: `http://squid_user:asdf123@localhost:${auth_proxy.port}`, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(response.status).toBe(403); | ||||||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||
| expect(true).toBeFalsy(); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| it.each([ | ||||||||||||||||||||||||||||||||||||||||||||
| [undefined, undefined], | ||||||||||||||||||||||||||||||||||||||||||||
| ["", ""], | ||||||||||||||||||||||||||||||||||||||||||||
| ["''", "''"], | ||||||||||||||||||||||||||||||||||||||||||||
| ['""', '""'], | ||||||||||||||||||||||||||||||||||||||||||||
| ])("test proxy env, http_proxy=%s https_proxy=%s", async (http_proxy, https_proxy) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const path = `${tmpdir()}/bun-test-http-proxy-env-${Date.now()}.ts`; | ||||||||||||||||||||||||||||||||||||||||||||
| fs.writeFileSync(path, 'await fetch("https://example.com");'); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const { stderr, exitCode } = Bun.spawnSync({ | ||||||||||||||||||||||||||||||||||||||||||||
| cmd: [bunExe(), "run", path], | ||||||||||||||||||||||||||||||||||||||||||||
| env: { | ||||||||||||||||||||||||||||||||||||||||||||
| ...bunEnv, | ||||||||||||||||||||||||||||||||||||||||||||
| http_proxy: http_proxy, | ||||||||||||||||||||||||||||||||||||||||||||
| https_proxy: https_proxy, | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| stdout: "inherit", | ||||||||||||||||||||||||||||||||||||||||||||
| stderr: "pipe", | ||||||||||||||||||||||||||||||||||||||||||||
| it("simultaneous proxy auth failures should not hang", async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const url = `http://localhost:${server.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
| const invalidProxy = `http://localhost:${auth_proxy.port}`; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // First batch: 5 simultaneous fetches with invalid credentials | ||||||||||||||||||||||||||||||||||||||||||||
| const firstBatch = await Promise.all([ | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(firstBatch.map(r => r.status)).toEqual([407, 407, 407, 407, 407]); | ||||||||||||||||||||||||||||||||||||||||||||
| await Promise.all(firstBatch.map(r => r.text())).catch(() => {}); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // Second batch: immediately send another 5 | ||||||||||||||||||||||||||||||||||||||||||||
| // Before the fix, these would hang due to keep-alive on failed proxy connections | ||||||||||||||||||||||||||||||||||||||||||||
| const secondBatch = await Promise.all([ | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| fetch(url, { proxy: invalidProxy }), | ||||||||||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(secondBatch.map(r => r.status)).toEqual([407, 407, 407, 407, 407]); | ||||||||||||||||||||||||||||||||||||||||||||
| await Promise.all(secondBatch.map(r => r.text())).catch(() => {}); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| it.each([ | ||||||||||||||||||||||||||||||||||||||||||||
| [undefined, undefined], | ||||||||||||||||||||||||||||||||||||||||||||
| ["", ""], | ||||||||||||||||||||||||||||||||||||||||||||
| ["''", "''"], | ||||||||||||||||||||||||||||||||||||||||||||
| ['""', '""'], | ||||||||||||||||||||||||||||||||||||||||||||
| ])("test proxy env, http_proxy=%s https_proxy=%s", async (http_proxy, https_proxy) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const { exited, stderr: stream } = Bun.spawn({ | ||||||||||||||||||||||||||||||||||||||||||||
| cmd: [bunExe(), "-e", 'await fetch("https://example.com")'], | ||||||||||||||||||||||||||||||||||||||||||||
| env: { | ||||||||||||||||||||||||||||||||||||||||||||
| ...bunEnv, | ||||||||||||||||||||||||||||||||||||||||||||
| http_proxy: http_proxy, | ||||||||||||||||||||||||||||||||||||||||||||
| https_proxy: https_proxy, | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| stdout: "inherit", | ||||||||||||||||||||||||||||||||||||||||||||
| stderr: "pipe", | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const [exitCode, stderr] = await Promise.all([exited, stream.text()]); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| expect(stderr.includes("FailedToOpenSocket: Was there a typo in the url or port?")).toBe(false); | ||||||||||||||||||||||||||||||||||||||||||||
| expect(exitCode).toBe(0); | ||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||
| fs.unlinkSync(path); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| it.each([ | ||||||||||||||||||||||||||||||||||||||||||||
| // Empty entries in NO_PROXY should not cause out-of-bounds access | ||||||||||||||||||||||||||||||||||||||||||||
| ["localhost, , example.com"], | ||||||||||||||||||||||||||||||||||||||||||||
| [",localhost,example.com"], | ||||||||||||||||||||||||||||||||||||||||||||
| ["localhost,example.com,"], | ||||||||||||||||||||||||||||||||||||||||||||
| [" , , "], | ||||||||||||||||||||||||||||||||||||||||||||
| [",,,"], | ||||||||||||||||||||||||||||||||||||||||||||
| [". , .. , ..."], | ||||||||||||||||||||||||||||||||||||||||||||
| ])("NO_PROXY with empty entries does not crash: %s", async no_proxy => { | ||||||||||||||||||||||||||||||||||||||||||||
| // We just need to verify parsing NO_PROXY doesn't crash. | ||||||||||||||||||||||||||||||||||||||||||||
| // The fetch target doesn't matter - NO_PROXY parsing happens before the connection. | ||||||||||||||||||||||||||||||||||||||||||||
| const { exitCode } = Bun.spawnSync({ | ||||||||||||||||||||||||||||||||||||||||||||
| cmd: [bunExe(), "-e", `fetch("http://localhost:1").catch(() => {})`], | ||||||||||||||||||||||||||||||||||||||||||||
| env: { | ||||||||||||||||||||||||||||||||||||||||||||
| ...bunEnv, | ||||||||||||||||||||||||||||||||||||||||||||
| http_proxy: "http://127.0.0.1:1", | ||||||||||||||||||||||||||||||||||||||||||||
| NO_PROXY: no_proxy, | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| expect(exitCode).toBe(0); | ||||||||||||||||||||||||||||||||||||||||||||
| it.each([ | ||||||||||||||||||||||||||||||||||||||||||||
| // Empty entries in NO_PROXY should not cause out-of-bounds access | ||||||||||||||||||||||||||||||||||||||||||||
| ["localhost, , example.com"], | ||||||||||||||||||||||||||||||||||||||||||||
| [",localhost,example.com"], | ||||||||||||||||||||||||||||||||||||||||||||
| ["localhost,example.com,"], | ||||||||||||||||||||||||||||||||||||||||||||
| [" , , "], | ||||||||||||||||||||||||||||||||||||||||||||
| [",,,"], | ||||||||||||||||||||||||||||||||||||||||||||
| [". , .. , ..."], | ||||||||||||||||||||||||||||||||||||||||||||
| ])("NO_PROXY with empty entries does not crash: %s", async no_proxy => { | ||||||||||||||||||||||||||||||||||||||||||||
| // We just need to verify parsing NO_PROXY doesn't crash. | ||||||||||||||||||||||||||||||||||||||||||||
| // The fetch target doesn't matter - NO_PROXY parsing happens before the connection. | ||||||||||||||||||||||||||||||||||||||||||||
| const { exited, stderr: stream } = Bun.spawn({ | ||||||||||||||||||||||||||||||||||||||||||||
| cmd: [bunExe(), "-e", `fetch("http://localhost:1").catch(() => {})`], | ||||||||||||||||||||||||||||||||||||||||||||
| env: { | ||||||||||||||||||||||||||||||||||||||||||||
| ...bunEnv, | ||||||||||||||||||||||||||||||||||||||||||||
| http_proxy: "http://127.0.0.1:1", | ||||||||||||||||||||||||||||||||||||||||||||
| NO_PROXY: no_proxy, | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| stderr: "pipe", | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| const [exitCode, stderr] = await Promise.all([exited, stream.text()]); | ||||||||||||||||||||||||||||||||||||||||||||
| if (exitCode !== 0) { | ||||||||||||||||||||||||||||||||||||||||||||
| console.error("stderr:", stderr); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| expect(exitCode).toBe(0); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Minor wording improvement suggestion.
The comment dropped "it" ("is not possible" vs "it is not possible"). While grammatically acceptable, restoring "it" would improve readability.
♻️ Suggested refinement
📝 Committable suggestion
🤖 Prompt for AI Agents