Skip to content

Commit

Permalink
http: support http proxy for fetch under NODE_USE_ENV_PROXY
Browse files Browse the repository at this point in the history
  • Loading branch information
joyeecheung committed Mar 4, 2025
1 parent 52ac448 commit 18c0d95
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lib/internal/process/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ function prepareExecution(options) {
initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
setupHttpProxy();

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down Expand Up @@ -154,6 +155,17 @@ function prepareExecution(options) {
return mainEntry;
}

function setupHttpProxy() {
if (process.env.NODE_USE_ENV_PROXY &&
(process.env.HTTP_PROXY || process.env.HTTPS_PROXY)) {
const { setGlobalDispatcher, EnvHttpProxyAgent } = require('internal/deps/undici/undici');
const envHttpProxyAgent = new EnvHttpProxyAgent();
setGlobalDispatcher(envHttpProxyAgent);
// TODO(joyeecheung): handle http/https global agents and perhaps Agent constructor
// behaviors.
}
}

function setupUserModules(forceDefaultLoader = false) {
initializeCJSLoader();
initializeESMLoader(forceDefaultLoader);
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/fetch-and-log.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const address = process.env.SERVER_ADDRESS;
const response = await fetch(address);
const body = await response.text();
console.log(body);
22 changes: 22 additions & 0 deletions test/fixtures/proxy-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const net = require('net');

exports.onConnect = function (req, clientSocket, head) {
const [hostname, port] = req.url.split(':');

const serverSocket = net.connect(port, hostname, () => {
clientSocket.write(
'HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n'
);
serverSocket.write(head);
clientSocket.pipe(serverSocket);
serverSocket.pipe(clientSocket);
});

serverSocket.on('error', (err) => {
console.error('Error on CONNECT tunnel:', err.message);
clientSocket.write('HTTP/1.1 500 Connection Error\r\n\r\n');
clientSocket.end();
});
};
64 changes: 64 additions & 0 deletions test/parallel/test-http-proxy-fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict';

const common = require('../common');
const fixtures = require('../common/fixtures');
const assert = require('assert');
const { spawn } = require('child_process');
const http = require('http');
const { onConnect } = require('../fixtures/proxy-handler');

// Start a server to process the final request.
const server = http.createServer((req, res) => {
res.end('Hello world');
});
server.on('error', (err) => { console.log('Server error', err); });

server.listen(0, common.mustCall(() => {
// Start a proxy server to tunnel the request.
const proxy = http.createServer();
// If the request does not go through the proxy server, common.mustCall fails.
proxy.on('connect', common.mustCall((req, clientSocket, head) => {
console.log('Proxying CONNECT', req.url, req.headers);
assert.strictEqual(req.url, `localhost:${server.address().port}`);
onConnect(req, clientSocket, head);
}));
proxy.on('error', (err) => { console.log('Proxy error', err); });

proxy.listen(0, common.mustCall(() => {
const proxyAddress = `http://localhost:${proxy.address().port}`;
const serverAddress = `http://localhost:${server.address().port}`;
const child = spawn(process.execPath,
[fixtures.path('fetch-and-log.mjs')],
{
env: {
...process.env,
HTTP_PROXY: proxyAddress,
NODE_USE_ENV_PROXY: true,
SERVER_ADDRESS: serverAddress,
},
});

const stderr = [];
const stdout = [];
child.stderr.on('data', (chunk) => {
stderr.push(chunk);
});
child.stdout.on('data', (chunk) => {
stdout.push(chunk);
});

child.on('exit', common.mustCall(function(code, signal) {
proxy.close();
server.close();

console.log('--- stderr ---');
console.log(Buffer.concat(stderr).toString());
console.log('--- stdout ---');
const stdoutStr = Buffer.concat(stdout).toString();
console.log(stdoutStr);
assert.strictEqual(stdoutStr.trim(), 'Hello world');
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
}));
}));
}));

0 comments on commit 18c0d95

Please sign in to comment.