paperclip/tests/e2e/fetch-allowed-port.ts

40 lines
1.5 KiB
TypeScript

import type { Server } from "node:http";
import type { AddressInfo } from "node:net";
// WHATWG Fetch blocks a fixed list of ports. Node's HTTP adapter uses fetch,
// so e2e mock servers must avoid ephemeral assignments like :6000.
const FETCH_BLOCKED_PORTS = new Set([
1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 69, 77, 79,
87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 137,
139, 143, 161, 179, 389, 427, 465, 512, 513, 514, 515, 526, 530, 531, 532, 540,
548, 554, 556, 563, 587, 601, 636, 989, 990, 993, 995, 1719, 1720, 1723,
2049, 3659, 4045, 4190, 5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668, 6669,
6697, 10080,
]);
export async function listenOnFetchAllowedPort(server: Server): Promise<number> {
for (let attempt = 0; attempt < 20; attempt += 1) {
await new Promise<void>((resolve, reject) => {
const onError = (error: Error) => {
server.off("error", onError);
reject(error);
};
server.once("error", onError);
server.listen(0, "127.0.0.1", () => {
server.off("error", onError);
resolve();
});
});
const address = server.address() as AddressInfo | null;
const port = address?.port;
if (port && !FETCH_BLOCKED_PORTS.has(port)) return port;
await new Promise<void>((resolve, reject) => {
server.close((error) => error ? reject(error) : resolve());
});
}
throw new Error("Unable to allocate a Fetch-allowed local test server port");
}