Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
test: deflake connection refused proxy tests
Previously the tests tries to use UDP ports to fabricate
ECONNREFUSED which is incorrect - UDP ports use different
namespaces, so the port can have valid TCP listeners.

This patch updates the test to fabricate the ECONNREFUSED
error by using the port of a recently closed HTTP server.
If the ephemeral port happens to be still open, try to get
a different one until we succeed.
  • Loading branch information
joyeecheung committed Aug 14, 2025
commit 005a9e308471d802309713cc985319e2ee1c588c
51 changes: 30 additions & 21 deletions test/client-proxy/test-http-proxy-request-connection-refused.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// handle it correctly.

import * as common from '../common/index.mjs';
import assert from 'node:assert';
import http from 'node:http';
import assert from 'node:assert';
import { once } from 'events';
import { runProxiedRequest } from '../common/proxy-server.js';
import dgram from 'node:dgram';

const server = http.createServer(common.mustNotCall());
server.on('error', common.mustNotCall((err) => { console.error('Server error', err); }));
Expand All @@ -16,24 +15,34 @@ await once(server, 'listening');
const serverHost = `localhost:${server.address().port}`;
const requestUrl = `http://${serverHost}/test`;

// Make it fail on connection refused by connecting to a UDP port with TCP.
const udp = dgram.createSocket('udp4');
udp.bind(0, '127.0.0.1');
await once(udp, 'listening');

const port = udp.address().port;

const { code, signal, stderr, stdout } = await runProxiedRequest({
NODE_USE_ENV_PROXY: 1,
REQUEST_URL: requestUrl,
HTTP_PROXY: `http://localhost:${port}`,
});

// The proxy client should get a connection refused error.
assert.match(stderr, /Error.*connect ECONNREFUSED/);
assert.strictEqual(stdout.trim(), '');
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
let maxRetries = 10;
let foundRefused = false;
while (maxRetries-- > 0) {
// Make it fail on connection refused by connecting to a port of a closed server.
// If it succeeds, get a different port and retry.
const proxy = http.createServer((req, res) => {
res.destroy();
});
proxy.listen(0);
await once(proxy, 'listening');
const port = proxy.address().port;
proxy.close();
await once(proxy, 'close');

console.log(`Trying proxy at port ${port}`);
const { stderr } = await runProxiedRequest({
NODE_USE_ENV_PROXY: 1,
REQUEST_URL: requestUrl,
HTTP_PROXY: `http://localhost:${port}`,
REQUEST_TIMEOUT: 5000,
});

foundRefused = /Error.*connect ECONNREFUSED/.test(stderr);
if (foundRefused) {
// The proxy client should get a connection refused error.
break;
}
}

server.close();
udp.close();
assert(foundRefused, 'Expected ECONNREFUSED error from proxy request');
51 changes: 31 additions & 20 deletions test/client-proxy/test-https-proxy-request-connection-refused.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import fixtures from '../common/fixtures.js';
import assert from 'node:assert';
import { once } from 'events';
import { runProxiedRequest } from '../common/proxy-server.js';
import dgram from 'node:dgram';
import http from 'node:http';

if (!common.hasCrypto)
common.skip('missing crypto');
Expand All @@ -25,24 +25,35 @@ await once(server, 'listening');
const serverHost = `localhost:${server.address().port}`;
const requestUrl = `https://${serverHost}/test`;

// Make it fail on connection refused by connecting to a UDP port with TCP.
const udp = dgram.createSocket('udp4');
udp.bind(0, '127.0.0.1');
await once(udp, 'listening');
const port = udp.address().port;

const { code, signal, stderr, stdout } = await runProxiedRequest({
NODE_USE_ENV_PROXY: 1,
REQUEST_URL: requestUrl,
HTTPS_PROXY: `http://localhost:${port}`,
NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'fake-startcom-root-cert.pem'),
});

// The proxy client should get a connection refused error.
assert.match(stderr, /Error.*connect ECONNREFUSED/);
assert.strictEqual(stdout.trim(), '');
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
let maxRetries = 10;
let foundRefused = false;
while (maxRetries-- > 0) {
// Make it fail on connection refused by connecting to a port of a closed server.
// If it succeeds, get a different port and retry.
const proxy = http.createServer((req, res) => {
res.destroy();
});
proxy.listen(0);
await once(proxy, 'listening');
const port = proxy.address().port;
proxy.close();
await once(proxy, 'close');

console.log(`Trying proxy at port ${port}`);
const { stderr } = await runProxiedRequest({
NODE_USE_ENV_PROXY: 1,
REQUEST_URL: requestUrl,
HTTPS_PROXY: `http://localhost:${port}`,
NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'fake-startcom-root-cert.pem'),
REQUEST_TIMEOUT: 5000,
});

foundRefused = /Error.*connect ECONNREFUSED/.test(stderr);
if (foundRefused) {
// The proxy client should get a connection refused error.
break;
}
}

server.close();
udp.close();
assert(foundRefused, 'Expected ECONNREFUSED error from proxy request');
Loading