mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
PR-URL: https://github.com/nodejs/node/pull/60175 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
94 lines
3.5 KiB
JavaScript
94 lines
3.5 KiB
JavaScript
// This tests that invalid hosts or ports with carriage return or newline characters
|
|
// in HTTP request urls are stripped away before being sent to the server.
|
|
|
|
import * as common from '../common/index.mjs';
|
|
import assert from 'node:assert';
|
|
import http from 'node:http';
|
|
import { once } from 'events';
|
|
import { inspect } from 'node:util';
|
|
import fixtures from '../common/fixtures.js';
|
|
import { Worker } from 'node:worker_threads';
|
|
|
|
const expectedProxyLogs = new Set();
|
|
const proxyWorker = new Worker(fixtures.path('proxy-server-worker.js'));
|
|
|
|
proxyWorker.on('message', common.mustCall((message) => {
|
|
console.log('Received message from worker:', message.type);
|
|
if (message.type === 'proxy-listening') {
|
|
startTest(message.port).then(common.mustCall());
|
|
} else if (message.type === 'proxy-stopped') {
|
|
assert.deepStrictEqual(new Set(message.logs), expectedProxyLogs);
|
|
// Close the server after the proxy is stopped.
|
|
proxyWorker.terminate();
|
|
}
|
|
}, 2));
|
|
|
|
const requests = new Set();
|
|
// Create a server that records the requests it gets.
|
|
const server = http.createServer((req, res) => {
|
|
requests.add(`http://localhost:${server.address().port}${req.url}`);
|
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
res.end(`Response for ${req.url}`);
|
|
});
|
|
proxyWorker.on('exit', common.mustCall(() => {
|
|
server.close();
|
|
}));
|
|
|
|
async function startTest(proxyPort) {
|
|
// Start a minimal proxy server in a worker, we don't do it in this thread
|
|
// because we'll mutate the global http agent here.
|
|
http.globalAgent = new http.Agent({
|
|
proxyEnv: {
|
|
HTTP_PROXY: `http://localhost:${proxyPort}`,
|
|
},
|
|
});
|
|
|
|
server.listen(0);
|
|
await once(server, 'listening');
|
|
server.on('error', common.mustNotCall());
|
|
const port = server.address().port.toString();
|
|
|
|
const testCases = [
|
|
{ host: 'local\rhost', port: port, path: '/carriage-return-in-host' },
|
|
{ host: 'local\nhost', port: port, path: '/newline-in-host' },
|
|
{ host: 'local\r\nhost', port: port, path: '/crlf-in-host' },
|
|
{ host: 'localhost', port: port.substring(0, 1) + '\r' + port.substring(1), path: '/carriage-return-in-port' },
|
|
{ host: 'localhost', port: port.substring(0, 1) + '\n' + port.substring(1), path: '/newline-in-port' },
|
|
{ host: 'localhost', port: port.substring(0, 1) + '\r\n' + port.substring(1), path: '/crlf-in-port' },
|
|
];
|
|
const severHost = `localhost:${server.address().port}`;
|
|
|
|
let counter = testCases.length;
|
|
const expectedUrls = new Set();
|
|
for (const testCase of testCases) {
|
|
const url = `http://${testCase.host}:${testCase.port}${testCase.path}`;
|
|
// The invalid characters should all be stripped away before being sent.
|
|
const cleanUrl = url.replaceAll(/\r|\n/g, '');
|
|
expectedUrls.add(cleanUrl);
|
|
expectedProxyLogs.add({
|
|
method: 'GET',
|
|
url: cleanUrl,
|
|
headers: {
|
|
'host': severHost,
|
|
'connection': 'close',
|
|
'proxy-connection': 'close',
|
|
},
|
|
});
|
|
http.request(url, common.mustCall((res) => {
|
|
res.on('error', common.mustNotCall());
|
|
res.setEncoding('utf8');
|
|
res.on('data', () => {});
|
|
res.on('end', common.mustCall(() => {
|
|
console.log(`#${counter--} ended response for: ${inspect(url)}`);
|
|
// Finished all test cases.
|
|
if (counter === 0) {
|
|
// Check that the requests received by the server have sanitized URLs.
|
|
assert.deepStrictEqual(requests, expectedUrls);
|
|
console.log('Sending stop-proxy message to worker');
|
|
proxyWorker.postMessage({ type: 'stop-proxy' });
|
|
}
|
|
}));
|
|
})).on('error', common.mustNotCall()).end();
|
|
}
|
|
}
|