node/test/common/proxy-server.js
Joyee Cheung 5a7b7d2124
Some checks are pending
Coverage Linux (without intl) / coverage-linux-without-intl (push) Waiting to run
Coverage Linux / coverage-linux (push) Waiting to run
Coverage Windows / coverage-windows (push) Waiting to run
Test and upload documentation to artifacts / build-docs (push) Waiting to run
Linters / lint-addon-docs (push) Waiting to run
Linters / lint-cpp (push) Waiting to run
Linters / format-cpp (push) Waiting to run
Linters / lint-js-and-md (push) Waiting to run
Linters / lint-py (push) Waiting to run
Linters / lint-yaml (push) Waiting to run
Linters / lint-sh (push) Waiting to run
Linters / lint-codeowners (push) Waiting to run
Linters / lint-pr-url (push) Waiting to run
Linters / lint-readme (push) Waiting to run
Notify on Push / Notify on Force Push on `main` (push) Waiting to run
Notify on Push / Notify on Push on `main` that lacks metadata (push) Waiting to run
Scorecard supply-chain security / Scorecard analysis (push) Waiting to run
http: support http proxy for fetch under NODE_USE_ENV_PROXY
When enabled, Node.js parses the `HTTP_PROXY`, `HTTPS_PROXY` and
`NO_PROXY` environment variables during startup, and tunnels requests
over the specified proxy.

This currently only affects requests sent over `fetch()`. Support for
other built-in `http` and `https` methods is under way.

PR-URL: https://github.com/nodejs/node/pull/57165
Refs: https://github.com/nodejs/undici/issues/1650
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2025-03-20 14:35:05 +00:00

101 lines
2.4 KiB
JavaScript

'use strict';
const net = require('net');
const http = require('http');
const assert = require('assert');
function logRequest(logs, req) {
logs.push({
method: req.method,
url: req.url,
headers: { ...req.headers },
});
}
// This creates a minimal proxy server that logs the requests it gets
// to an array before performing proxying.
exports.createProxyServer = function() {
const logs = [];
const proxy = http.createServer();
proxy.on('request', (req, res) => {
logRequest(logs, req);
const [hostname, port] = req.headers.host.split(':');
const targetPort = port || 80;
const options = {
hostname: hostname,
port: targetPort,
path: req.url,
method: req.method,
headers: req.headers,
};
const proxyReq = http.request(options, (proxyRes) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers);
proxyRes.pipe(res, { end: true });
});
proxyReq.on('error', (err) => {
logs.push({ error: err, source: 'proxy request' });
res.writeHead(500);
res.end('Proxy error: ' + err.message);
});
req.pipe(proxyReq, { end: true });
});
proxy.on('connect', (req, res, head) => {
logRequest(logs, req);
const [hostname, port] = req.url.split(':');
const proxyReq = net.connect(port, hostname, () => {
res.write(
'HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n',
);
proxyReq.write(head);
res.pipe(proxyReq);
proxyReq.pipe(res);
});
proxyReq.on('error', (err) => {
logs.push({ error: err, source: 'proxy request' });
res.write('HTTP/1.1 500 Connection Error\r\n\r\n');
res.end('Proxy error: ' + err.message);
});
});
proxy.on('error', (err) => {
logs.push({ error: err, source: 'proxy server' });
});
return { proxy, logs };
};
exports.checkProxiedRequest = async function(envExtension, expectation) {
const { spawnPromisified } = require('./');
const fixtures = require('./fixtures');
const { code, signal, stdout, stderr } = await spawnPromisified(
process.execPath,
[fixtures.path('fetch-and-log.mjs')], {
env: {
...process.env,
...envExtension,
},
});
assert.deepStrictEqual({
stderr: stderr.trim(),
stdout: stdout.trim(),
code,
signal,
}, {
stderr: '',
code: 0,
signal: null,
...expectation,
});
};