Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix: parse port to number type if provided in as string (#2610)
Browse files Browse the repository at this point in the history
* Fixes #2580
* Improved validation and parsing of port value - inspiration from nodejs internal port validator
  • Loading branch information
jeffsmale90 authored Mar 17, 2022
1 parent 4f3af10 commit 386771d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
25 changes: 21 additions & 4 deletions src/packages/core/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,23 @@ export class Server<
host = null;
}
const callbackIsFunction = typeof callback === "function";

// Method signature specifies port: number, but we parse a string if provided
// inspiration taken from nodejs internal port validator
// https://github.com/nodejs/node/blob/8c4b8b201ada6b76d5306c9c7f352e45087fb4a9/lib/internal/validators.js#L208-L219
if ((typeof port !== 'number' && typeof port !== 'string') ||
(typeof port === 'string' && (<string>port).trim().length === 0) ||
+port !== (+port >>> 0) ||
port > 0xFFFF ||
port === 0) {
const err = new Error(`Port should be >= 0 and < 65536. Received ${port}.`);

return callbackIsFunction
? process.nextTick(callback!, err)
: Promise.reject(err);
}
const portNumber = +port;

const status = this.#status;
if (status === ServerStatus.closing) {
// if closing
Expand All @@ -195,7 +212,7 @@ export class Server<
} else if ((status & ServerStatus.openingOrOpen) !== 0) {
// if opening or open
const err = new Error(
`Server is already open, or is opening, on port: ${port}.`
`Server is already open, or is opening, on port: ${portNumber}.`
);
return callbackIsFunction
? process.nextTick(callback!, err)
Expand All @@ -214,11 +231,11 @@ export class Server<
host
? (this.#app as any).listen(
host,
port,
portNumber,
LIBUS_LISTEN_EXCLUSIVE_PORT,
resolve
)
: this.#app.listen(port, LIBUS_LISTEN_EXCLUSIVE_PORT, resolve);
: this.#app.listen(portNumber, LIBUS_LISTEN_EXCLUSIVE_PORT, resolve);
}
).then(listenSocket => {
if (listenSocket) {
Expand All @@ -228,7 +245,7 @@ export class Server<
this.#status = ServerStatus.closed;
const err = new Error(
`listen EADDRINUSE: address already in use ${host || DEFAULT_HOST
}:${port}.`
}:${portNumber}.`
);
throw err;
}
Expand Down
49 changes: 45 additions & 4 deletions src/packages/core/tests/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ describe("server", () => {
(process.env.GITHUB_ACTION ? describe : describe.skip)("listen", function () {
/**
* Sends a post request to the server and returns the response.
* @param address
* @param port
* @param json
* @returns
* @param address
* @param port
* @param json
* @returns
*/
function post(host: string, port: number, json: any) {
const data = JSON.stringify(json);
Expand Down Expand Up @@ -299,6 +299,47 @@ describe("server", () => {
});
});

it("accepts port as number type or binary, octal, decimal or hexadecimal string", async () => {
const validPorts = [
port, `0b${port.toString(2)}`,
`0o${port.toString(8)}`, port.toString(10),
`0x${port.toString(16)}`
];

for (const specificPort of validPorts) {
s = Ganache.server(defaultOptions);
await s.listen(<any>specificPort);

try {
const req = request.post(`http://localhost:${+specificPort}`);
await req.send(jsonRpcJson);
} finally {
await teardown();
}
}
});

it("fails with invalid ports", async () => {
const invalidPorts = [
-1, 'a', {}, [], false, true,
0xFFFF + 1, Infinity, -Infinity, NaN,
undefined, null, '', ' ', 1.1, '0x',
'-0x1', '-0o1', '-0b1', '0o', '0b', 0
];

for (const specificPort of invalidPorts) {
s = Ganache.server(defaultOptions);

try {
await assert.rejects(s.listen(<any>specificPort), {
message: `Port should be >= 0 and < 65536. Received ${specificPort}.`
});
} finally {
await teardown();
}
}
});

it("fails to `.listen()` twice, Promise", async () => {
await setup();
try {
Expand Down

0 comments on commit 386771d

Please sign in to comment.