Skip to content

Commit ba769a6

Browse files
author
vhess
committed
Address code review issues
1 parent 7e5f891 commit ba769a6

File tree

8 files changed

+70
-83
lines changed

8 files changed

+70
-83
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ http-proxy-3 supports HTTP/2 through the native fetch API. When fetch is enabled
452452

453453
```js
454454
import { createProxyServer } from "http-proxy-3";
455-
import { Agent } from "undici";
455+
import { Agent, setGlobalDispatcher } from "undici";
456456

457457
// Either enable HTTP/2 for all fetch operations
458458
setGlobalDispatcher(new Agent({ allowH2: true }));

biome.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/2.2.5/schema.json",
3+
"vcs": {
4+
"enabled": false,
5+
"clientKind": "git",
6+
"useIgnoreFile": false
7+
},
8+
"files": {
9+
"ignoreUnknown": false
10+
},
11+
"formatter": {
12+
"enabled": true,
13+
"indentStyle": "space",
14+
"lineWidth": 120
15+
},
16+
"linter": {
17+
"enabled": true,
18+
"rules": {
19+
"recommended": true
20+
}
21+
},
22+
"javascript": {
23+
"formatter": {
24+
"quoteStyle": "double"
25+
}
26+
},
27+
"assist": {
28+
"enabled": true,
29+
"actions": {
30+
"source": {
31+
"organizeImports": "on"
32+
}
33+
}
34+
}
35+
}

lib/http-proxy/passes/web-incoming.ts

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ The names of passes are exported as WEB_PASSES from this module.
77
88
*/
99

10-
import type {
11-
IncomingMessage as Request,
12-
ServerResponse as Response,
13-
} from "node:http";
10+
import type { IncomingMessage as Request, ServerResponse as Response } from "node:http";
1411
import * as http from "node:http";
1512
import * as https from "node:https";
1613
import type { Socket } from "node:net";
@@ -41,10 +38,7 @@ const nativeAgents = { http, https };
4138

4239
// Sets `content-length` to '0' if request is of DELETE type.
4340
export function deleteLength(req: Request) {
44-
if (
45-
(req.method === "DELETE" || req.method === "OPTIONS") &&
46-
!req.headers["content-length"]
47-
) {
41+
if ((req.method === "DELETE" || req.method === "OPTIONS") && !req.headers["content-length"]) {
4842
req.headers["content-length"] = "0";
4943
delete req.headers["transfer-encoding"];
5044
}
@@ -72,13 +66,10 @@ export function XHeaders(req: Request, _res: Response, options: ServerOptions) {
7266

7367
for (const header of ["for", "port", "proto"] as const) {
7468
req.headers["x-forwarded-" + header] =
75-
(req.headers["x-forwarded-" + header] || "") +
76-
(req.headers["x-forwarded-" + header] ? "," : "") +
77-
values[header];
69+
(req.headers["x-forwarded-" + header] || "") + (req.headers["x-forwarded-" + header] ? "," : "") + values[header];
7870
}
7971

80-
req.headers["x-forwarded-host"] =
81-
req.headers["x-forwarded-host"] || req.headers["host"] || "";
72+
req.headers["x-forwarded-host"] = req.headers["x-forwarded-host"] || req.headers["host"] || "";
8273
}
8374

8475
// Does the actual proxying. If `forward` is enabled fires up
@@ -106,12 +97,7 @@ export function stream(
10697
if (options.forward) {
10798
// forward enabled, so just pipe the request
10899
const proto = options.forward.protocol === "https:" ? https : http;
109-
const outgoingOptions = common.setupOutgoing(
110-
options.ssl || {},
111-
options,
112-
req,
113-
"forward",
114-
);
100+
const outgoingOptions = common.setupOutgoing(options.ssl || {}, options, req, "forward");
115101
const forwardReq = proto.request(outgoingOptions);
116102

117103
// error handler (e.g. ECONNRESET, ECONNREFUSED)
@@ -162,15 +148,9 @@ export function stream(
162148
req.on("error", proxyError);
163149
proxyReq.on("error", proxyError);
164150

165-
function createErrorHandler(
166-
proxyReq: http.ClientRequest,
167-
url: NormalizeProxyTarget<ProxyTargetUrl>,
168-
) {
151+
function createErrorHandler(proxyReq: http.ClientRequest, url: NormalizeProxyTarget<ProxyTargetUrl>) {
169152
return (err: Error) => {
170-
if (
171-
req.socket.destroyed &&
172-
(err as NodeJS.ErrnoException).code === "ECONNRESET"
173-
) {
153+
if (req.socket.destroyed && (err as NodeJS.ErrnoException).code === "ECONNRESET") {
174154
server.emit("econnreset", err, req, res, url);
175155
proxyReq.destroy();
176156
return;
@@ -236,10 +216,7 @@ async function stream2(
236216
};
237217

238218
req.on("error", (err: Error) => {
239-
if (
240-
req.socket.destroyed &&
241-
(err as NodeJS.ErrnoException).code === "ECONNRESET"
242-
) {
219+
if (req.socket.destroyed && (err as NodeJS.ErrnoException).code === "ECONNRESET") {
243220
const target = options.target || options.forward;
244221
if (target) {
245222
server.emit("econnreset", err, req, res, target);
@@ -249,19 +226,13 @@ async function stream2(
249226
handleError(err);
250227
});
251228

252-
const fetchOptions =
253-
options.fetch === true ? ({} as FetchOptions) : options.fetch;
229+
const fetchOptions = options.fetch === true ? ({} as FetchOptions) : options.fetch;
254230
if (!fetchOptions) {
255231
throw new Error("stream2 called without fetch options");
256232
}
257233

258234
if (options.forward) {
259-
const outgoingOptions = common.setupOutgoing(
260-
options.ssl || {},
261-
options,
262-
req,
263-
"forward",
264-
);
235+
const outgoingOptions = common.setupOutgoing(options.ssl || {}, options, req, "forward");
265236

266237
const requestOptions: RequestInit = {
267238
method: outgoingOptions.method,
@@ -290,10 +261,7 @@ async function stream2(
290261
}
291262

292263
try {
293-
const result = await fetch(
294-
new URL(outgoingOptions.url).origin + outgoingOptions.path,
295-
requestOptions,
296-
);
264+
const result = await fetch(new URL(outgoingOptions.url).origin + outgoingOptions.path, requestOptions);
297265

298266
// Call onAfterResponse callback for forward requests (though they typically don't expect responses)
299267
if (fetchOptions.onAfterResponse) {
@@ -341,6 +309,7 @@ async function stream2(
341309
requestOptions.body = options.buffer as Stream.Readable;
342310
} else if (req.method !== "GET" && req.method !== "HEAD") {
343311
requestOptions.body = req;
312+
requestOptions.duplex = "half";
344313
}
345314

346315
// Call onBeforeRequest callback before making the request
@@ -354,10 +323,7 @@ async function stream2(
354323
}
355324

356325
try {
357-
const response = await fetch(
358-
new URL(outgoingOptions.url).origin + outgoingOptions.path,
359-
requestOptions,
360-
);
326+
const response = await fetch(new URL(outgoingOptions.url).origin + outgoingOptions.path, requestOptions);
361327

362328
// Call onAfterResponse callback after receiving the response
363329
if (fetchOptions.onAfterResponse) {
@@ -402,9 +368,7 @@ async function stream2(
402368

403369
if (!res.writableEnded) {
404370
// Allow us to listen for when the proxy has completed
405-
const nodeStream = response.body
406-
? Readable.from(response.body as AsyncIterable<Uint8Array>)
407-
: null;
371+
const nodeStream = response.body ? Readable.from(response.body as AsyncIterable<Uint8Array>) : null;
408372

409373
if (nodeStream) {
410374
nodeStream.on("error", (err) => {
@@ -428,9 +392,7 @@ async function stream2(
428392
server?.emit("end", req, res, fakeProxyRes);
429393
}
430394
} catch (err) {
431-
if (err) {
432-
handleError(err as Error, options.target);
433-
}
395+
handleError(err as Error, options.target);
434396
}
435397
}
436398

lib/http-proxy/passes/web-outgoing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export function writeHeaders(
143143

144144
for (const key0 in proxyRes.headers) {
145145
let key = key0;
146-
if (_req.httpVersionMajor > 1 && (key === "connection") || key === "keep-alive") {
146+
if (_req.httpVersionMajor > 1 && (key === "connection" || key === "keep-alive")) {
147147
// don't send connection header to http2 client
148148
continue;
149149
}

lib/test/http/proxy-callbacks.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ describe("Fetch callback functions (onBeforeRequest and onAfterResponse)", () =>
6464
console.log(`Response received: ${response.status}`);
6565
}
6666
}
67-
}); servers.proxy = proxy.listen(ports.proxy);
67+
});
68+
servers.proxy = proxy.listen(ports.proxy);
6869

6970
// Make a request through the proxy
7071
const response = await fetch(`http://localhost:${ports.proxy}/test`);

lib/test/http/proxy-http2-to-http.test.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,15 @@ import * as httpProxy from "../..";
77
import getPort from "../get-port";
88
import { join } from "node:path";
99
import { readFile } from "node:fs/promises";
10-
import fetch from "node-fetch";
11-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
12-
import { Agent, setGlobalDispatcher } from "undici";
13-
14-
setGlobalDispatcher(new Agent({
15-
allowH2: true
16-
}));
10+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
11+
import { Agent, fetch } from "undici";
1712

13+
const TestAgent = new Agent({ allowH2: true });
1814

1915
const fixturesDir = join(__dirname, "..", "fixtures");
2016

2117
describe("Basic example of proxying over HTTPS to a target HTTP server", () => {
22-
let ports: Record<'http' | 'proxy', number>;
18+
let ports: Record<"http" | "proxy", number>;
2319
beforeAll(async () => {
2420
ports = { http: await getPort(), proxy: await getPort() };
2521
});
@@ -52,12 +48,12 @@ describe("Basic example of proxying over HTTPS to a target HTTP server", () => {
5248
});
5349

5450
it("Use fetch to test non-https server", async () => {
55-
const r = await (await fetch(`http://localhost:${ports.http}`)).text();
51+
const r = await (await fetch(`http://localhost:${ports.http}`, { dispatcher: TestAgent })).text();
5652
expect(r).toContain("hello http over https");
5753
});
5854

5955
it("Use fetch to test the ACTUAL https server", async () => {
60-
const r = await (await fetch(`https://localhost:${ports.proxy}`)).text();
56+
const r = await (await fetch(`https://localhost:${ports.proxy}`, { dispatcher: TestAgent })).text();
6157
expect(r).toContain("hello http over https");
6258
});
6359

lib/test/http/proxy-http2-to-http2.test.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
pnpm test proxy-https-to-https.test.ts
2+
pnpm test proxy-http2-to-http2.test.ts
33
44
*/
55

@@ -8,17 +8,15 @@ import * as httpProxy from "../..";
88
import getPort from "../get-port";
99
import { join } from "node:path";
1010
import { readFile } from "node:fs/promises";
11-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
12-
import { Agent, setGlobalDispatcher } from "undici";
11+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
12+
import { Agent, fetch } from "undici";
1313

14-
setGlobalDispatcher(new Agent({
15-
allowH2: true
16-
}));
14+
const TestAgent = new Agent({ allowH2: true, connect: { rejectUnauthorized: false } });
1715

1816
const fixturesDir = join(__dirname, "..", "fixtures");
1917

2018
describe("Basic example of proxying over HTTP2 to a target HTTP2 server", () => {
21-
let ports: Record<'http2' | 'proxy', number>;
19+
let ports: Record<"http2" | "proxy", number>;
2220
beforeAll(async () => {
2321
// Gets ports
2422
ports = { http2: await getPort(), proxy: await getPort() };
@@ -46,20 +44,20 @@ describe("Basic example of proxying over HTTP2 to a target HTTP2 server", () =>
4644
.createServer({
4745
target: `https://localhost:${ports.http2}`,
4846
ssl,
49-
fetch: { dispatcher: new Agent({ allowH2: true }) as any },
47+
fetch: { dispatcher: TestAgent as any },
5048
// without secure false, clients will fail and this is broken:
5149
secure: false,
5250
})
5351
.listen(ports.proxy);
5452
});
5553

5654
it("Use fetch to test direct non-proxied http2 server", async () => {
57-
const r = await (await fetch(`https://localhost:${ports.http2}`)).text();
55+
const r = await (await fetch(`https://localhost:${ports.http2}`, { dispatcher: TestAgent })).text();
5856
expect(r).toContain("hello over http2");
5957
});
6058

6159
it("Use fetch to test the proxy server", async () => {
62-
const r = await (await fetch(`https://localhost:${ports.proxy}`)).text();
60+
const r = await (await fetch(`https://localhost:${ports.proxy}`, { dispatcher: TestAgent })).text();
6361
expect(r).toContain("hello over http2");
6462
});
6563

lib/test/http/proxy-http2-to-https.test.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,12 @@ import * as httpProxy from "../..";
88
import getPort from "../get-port";
99
import { join } from "node:path";
1010
import { readFile } from "node:fs/promises";
11-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
12-
import { Agent, setGlobalDispatcher } from "undici";
13-
14-
setGlobalDispatcher(new Agent({
15-
allowH2: true
16-
}));
11+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
1712

1813
const fixturesDir = join(__dirname, "..", "fixtures");
1914

2015
describe("Basic example of proxying over HTTPS to a target HTTPS server", () => {
21-
let ports: Record<'https' | 'proxy', number>;
16+
let ports: Record<"https" | "proxy", number>;
2217
beforeAll(async () => {
2318
// Gets ports
2419
ports = { https: await getPort(), proxy: await getPort() };

0 commit comments

Comments
 (0)