From ebccc40c4f26d51e5a1b50365150eb22e5e7f6d2 Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Thu, 25 Mar 2021 18:10:22 -0700 Subject: [PATCH] fix(common): servers#startOnPreferredPort no graceful fallback #683 The code of the method was not waiting for a promise to resolve which was masking the underlying exception that the code was supposed to catch and examine in order to determine if it should perform a fallback of binding to port zero or not. Fixed it by making sure the initial try of the preferred port allocation is awaited for so that the exception is thrown where it is expected by the algorithm. Fixes #683 Signed-off-by: Peter Somogyvari --- .../src/main/typescript/servers.ts | 3 +- .../src/test/typescript/unit/servers.test.ts | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/cactus-common/src/main/typescript/servers.ts b/packages/cactus-common/src/main/typescript/servers.ts index 0d721f59c30..21ba40b4f36 100644 --- a/packages/cactus-common/src/main/typescript/servers.ts +++ b/packages/cactus-common/src/main/typescript/servers.ts @@ -86,7 +86,8 @@ export class Servers { ): Promise { if (preferredPort) { try { - return Servers.startOnPort(preferredPort, host); + const server = await Servers.startOnPort(preferredPort, host); + return server; } catch (ex) { // if something else went wrong we still want to just give up if (!ex.message.includes("EADDRINUSE")) { diff --git a/packages/cactus-common/src/test/typescript/unit/servers.test.ts b/packages/cactus-common/src/test/typescript/unit/servers.test.ts index f3917aacddf..693d3d899e9 100644 --- a/packages/cactus-common/src/test/typescript/unit/servers.test.ts +++ b/packages/cactus-common/src/test/typescript/unit/servers.test.ts @@ -1,4 +1,5 @@ import { createServer } from "http"; +import { AddressInfo } from "net"; import test, { Test } from "tape-promise/tape"; @@ -37,5 +38,34 @@ test("Servers", async (tParent: Test) => { t.end(); }); + test("Servers#startOnPreferredPort()", async (t: Test) => { + const prefPort = 4123; + const host = "0.0.0.0"; + const portBlocker = createServer(); + test.onFinish(() => portBlocker.close()); + const listenOptionsBlocker = { + server: portBlocker, + hostname: host, + port: prefPort, + }; + await Servers.listen(listenOptionsBlocker); + + await t.doesNotReject(async () => { + const server = await Servers.startOnPreferredPort(prefPort, host); + test.onFinish(() => server.close()); + t.ok(server, "Server returned truthy OK"); + const addressInfo = server.address() as AddressInfo; + t.ok(addressInfo, "AddressInfo returned truthy OK"); + t.ok(addressInfo.port, "AddressInfo.port returned truthy OK"); + t.doesNotEqual( + addressInfo.port, + prefPort, + "Peferred and actually allocated ports are different, therefore fallback is considered successful OK", + ); + }, "Servers.startOnPreferredPort falls back without throwing OK"); + + t.end(); + }); + tParent.end(); });