From bcd10b7859fc0b9325b72d2ec1637cc038ae9b3b Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 26 Sep 2023 12:14:25 -0400 Subject: [PATCH 01/23] start setting up port manager --- lib/PortManagerServer.ts | 23 +++++++++++++++++++++++ package.json | 2 ++ utils/detectPort.ts | 0 3 files changed, 25 insertions(+) create mode 100644 lib/PortManagerServer.ts create mode 100644 utils/detectPort.ts diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts new file mode 100644 index 00000000..c49132bf --- /dev/null +++ b/lib/PortManagerServer.ts @@ -0,0 +1,23 @@ +import express, { Express } from 'express'; + +type PortMap = { + [key: string]: number; +}; + +class PortManagerServer { + app?: Express; + ports: PortMap; + + constructor() { + this.ports = {}; + } + + init(): void { + if (this.app) { + throw new Error('Port manager server is already running'); + } + this.app = express(); + } +} + +export default PortManagerServer; diff --git a/package.json b/package.json index c9e6dcc5..c2b2712d 100644 --- a/package.json +++ b/package.json @@ -57,9 +57,11 @@ "./path": "./lib/path.js" }, "dependencies": { + "@types/express": "^4.17.18", "axios": "^1.3.5", "chokidar": "^3.5.3", "content-disposition": "^0.5.4", + "express": "^4.18.2", "extract-zip": "^2.0.1", "findup-sync": "^5.0.0", "fs-extra": "^11.1.0", diff --git a/utils/detectPort.ts b/utils/detectPort.ts new file mode 100644 index 00000000..e69de29b From d0285635b2c9deed7025aa53b055a37ecc1a4346 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 26 Sep 2023 14:54:09 -0400 Subject: [PATCH 02/23] detectPort first pass --- package.json | 1 + utils/detectPort.ts | 82 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/package.json b/package.json index c2b2712d..00b69c22 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ }, "dependencies": { "@types/express": "^4.17.18", + "address": "^2.0.1", "axios": "^1.3.5", "chokidar": "^3.5.3", "content-disposition": "^0.5.4", diff --git a/utils/detectPort.ts b/utils/detectPort.ts index e69de29b..5ac41ace 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -0,0 +1,82 @@ +import net, { AddressInfo } from 'net'; +import { ip } from 'address'; + +type NetError = Error & { + code: string; +}; + +type ListenCallback = (error: NetError | null, port: number) => void; + +const MAX_PORT_NUMBER = 65535; + +export function detectPort(port: number | null): Promise { + const portToUse = port || 0; + const maxPort = Math.min(portToUse + 10, MAX_PORT_NUMBER); + + return new Promise(resolve => { + tryListen(portToUse, maxPort, (_, resolvedPort) => { + resolve(resolvedPort); + }); + }); +} + +function tryListen(port: number, maxPort: number, callback: ListenCallback) { + const shouldGiveUp = port >= maxPort; + const nextPort = shouldGiveUp ? 0 : port + 1; + const nextMaxPort = shouldGiveUp ? 0 : maxPort; + + listen(port, undefined, (err, realPort) => { + // ignore random listening + if (port === 0) { + return callback(err, realPort); + } + + if (err) { + return tryListen(nextPort, nextMaxPort, callback); + } + + // 2. check 0.0.0.0 + listen(port, '0.0.0.0', err => { + if (err) { + return tryListen(nextPort, nextMaxPort, callback); + } + + // 3. check localhost + listen(port, 'localhost', err => { + if (err && err.code !== 'EADDRNOTAVAIL') { + return tryListen(nextPort, nextMaxPort, callback); + } + + // 4. check current ip + listen(port, ip(), (err, realPort) => { + if (err) { + return tryListen(nextPort, nextMaxPort, callback); + } + + callback(null, realPort); + }); + }); + }); + }); +} + +function listen( + port: number, + hostname: string | undefined, + callback: ListenCallback +): void { + const server = new net.Server(); + + server.on('error', (err: NetError) => { + server.close(); + if (err.code === 'ENOTFOUND') { + return callback(null, port); + } + }); + + server.listen(port, hostname, () => { + const addressInfo = server.address() as AddressInfo; + server.close(); + return callback(null, addressInfo.port); + }); +} From 82cd1692142f4391412ad816e74be86bc9c6b98d Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 26 Sep 2023 15:01:10 -0400 Subject: [PATCH 03/23] Fix port conflict bug --- utils/detectPort.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/detectPort.ts b/utils/detectPort.ts index 5ac41ace..fc057ed7 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -72,6 +72,7 @@ function listen( if (err.code === 'ENOTFOUND') { return callback(null, port); } + return callback(err, 0); }); server.listen(port, hostname, () => { From ecc19c837f8f0e1ba23924bf7ae06eaab9743bef Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 26 Sep 2023 15:56:21 -0400 Subject: [PATCH 04/23] Port manager get/set functionality --- constants/ports.ts | 3 ++ lib/PortManagerServer.ts | 59 ++++++++++++++++++++++++++++++++++++++-- utils/detectPort.ts | 8 ++++-- 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 constants/ports.ts diff --git a/constants/ports.ts b/constants/ports.ts new file mode 100644 index 00000000..d0fe422f --- /dev/null +++ b/constants/ports.ts @@ -0,0 +1,3 @@ +export const MIN_PORT_NUMBER = 1024; +export const MAX_PORT_NUMBER = 65535; +export const PORT_MANAGER_SERVER_PORT = 12345; diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index c49132bf..993812a7 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -1,7 +1,14 @@ -import express, { Express } from 'express'; +import express, { Express, Request, Response } from 'express'; + +import { detectPort } from '../utils/detectPort'; +import { + MIN_PORT_NUMBER, + MAX_PORT_NUMBER, + PORT_MANAGER_SERVER_PORT, +} from '../constants/ports'; type PortMap = { - [key: string]: number; + [instanceId: string]: number; }; class PortManagerServer { @@ -9,7 +16,9 @@ class PortManagerServer { ports: PortMap; constructor() { - this.ports = {}; + this.ports = { + yaa: 6000, + }; } init(): void { @@ -17,7 +26,51 @@ class PortManagerServer { throw new Error('Port manager server is already running'); } this.app = express(); + this.app.use(express.json()); + this.setupRoutes(); + this.app.listen(PORT_MANAGER_SERVER_PORT, () => + console.log('Running port manager') + ); + } + + setupRoutes(): void { + if (!this.app) { + return; + } + + this.app.get('/servers/:instanceId', this.getPortByInstanceId); + this.app.post('/servers', this.assignPortToServer); + } + + setPort(instanceId: string, port: number) { + this.ports[instanceId] = port; } + + getPortByInstanceId = (req: Request, res: Response): void => { + const { instanceId } = req.params; + const port = this.ports[instanceId]; + + if (port) { + res.send({ port }); + } else { + res + .status(404) + .send(`Could not find a server with instanceId ${instanceId}`); + } + }; + + assignPortToServer = async (req: Request, res: Response): Promise => { + const { instanceId, port } = req.body; + + if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { + res.status(400).send('Port must be between 1024 and 65535'); + } + + const portToUse = await detectPort(port); + this.setPort(instanceId, portToUse); + + res.send({ port: portToUse }); + }; } export default PortManagerServer; diff --git a/utils/detectPort.ts b/utils/detectPort.ts index fc057ed7..ab62cf4a 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -1,15 +1,19 @@ import net, { AddressInfo } from 'net'; import { ip } from 'address'; +import { MIN_PORT_NUMBER, MAX_PORT_NUMBER } from '../constants/ports'; + type NetError = Error & { code: string; }; type ListenCallback = (error: NetError | null, port: number) => void; -const MAX_PORT_NUMBER = 65535; - export function detectPort(port: number | null): Promise { + if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { + throw new Error('Port must be between 1024 and 65535'); + } + const portToUse = port || 0; const maxPort = Math.min(portToUse + 10, MAX_PORT_NUMBER); From 9b660ea09aac39d7f6f04e35f77274428a745f86 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 26 Sep 2023 16:51:42 -0400 Subject: [PATCH 05/23] add delete endpoint + clean some things up --- lib/PortManagerServer.ts | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index 993812a7..0467f76c 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -1,4 +1,5 @@ import express, { Express, Request, Response } from 'express'; +import { Server } from 'http'; import { detectPort } from '../utils/detectPort'; import { @@ -13,6 +14,7 @@ type PortMap = { class PortManagerServer { app?: Express; + server?: Server; ports: PortMap; constructor() { @@ -28,11 +30,17 @@ class PortManagerServer { this.app = express(); this.app.use(express.json()); this.setupRoutes(); - this.app.listen(PORT_MANAGER_SERVER_PORT, () => + this.server = this.app.listen(PORT_MANAGER_SERVER_PORT, () => console.log('Running port manager') ); } + close(): void { + if (this.server) { + this.server.close(); + } + } + setupRoutes(): void { if (!this.app) { return; @@ -40,12 +48,19 @@ class PortManagerServer { this.app.get('/servers/:instanceId', this.getPortByInstanceId); this.app.post('/servers', this.assignPortToServer); + this.app.delete('/servers/:instanceId', this.deleteServerInstance); } setPort(instanceId: string, port: number) { this.ports[instanceId] = port; } + send404(res: Response, instanceId: string) { + res + .status(404) + .send(`Could not find a server with instanceId ${instanceId}`); + } + getPortByInstanceId = (req: Request, res: Response): void => { const { instanceId } = req.params; const port = this.ports[instanceId]; @@ -53,15 +68,19 @@ class PortManagerServer { if (port) { res.send({ port }); } else { - res - .status(404) - .send(`Could not find a server with instanceId ${instanceId}`); + this.send404(res, instanceId); } }; assignPortToServer = async (req: Request, res: Response): Promise => { const { instanceId, port } = req.body; + if (this.ports[instanceId]) { + res + .status(409) + .send('This server instance has already been assigned a port'); + } + if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { res.status(400).send('Port must be between 1024 and 65535'); } @@ -71,6 +90,18 @@ class PortManagerServer { res.send({ port: portToUse }); }; + + deleteServerInstance = (req: Request, res: Response): void => { + const { instanceId } = req.params; + const port = this.ports[instanceId]; + + if (port) { + delete this.ports[instanceId]; + res.send(200); + } else { + this.send404(res, instanceId); + } + }; } export default PortManagerServer; From e1519074469aafe5782b9a218d2b5f1357ff6f7b Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 27 Sep 2023 13:36:07 -0400 Subject: [PATCH 06/23] port manager module first pass --- lib/PortManagerServer.ts | 16 ++++++++------- lib/portManager.ts | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 lib/portManager.ts diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index 0467f76c..85290cee 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -35,12 +35,6 @@ class PortManagerServer { ); } - close(): void { - if (this.server) { - this.server.close(); - } - } - setupRoutes(): void { if (!this.app) { return; @@ -49,6 +43,7 @@ class PortManagerServer { this.app.get('/servers/:instanceId', this.getPortByInstanceId); this.app.post('/servers', this.assignPortToServer); this.app.delete('/servers/:instanceId', this.deleteServerInstance); + this.app.post('/close', this.closeServer); } setPort(instanceId: string, port: number) { @@ -102,6 +97,13 @@ class PortManagerServer { this.send404(res, instanceId); } }; + + closeServer = (req: Request, res: Response): void => { + if (this.server) { + res.send(200); + this.server.close(); + } + }; } -export default PortManagerServer; +export default new PortManagerServer(); diff --git a/lib/portManager.ts b/lib/portManager.ts new file mode 100644 index 00000000..e33fe5c1 --- /dev/null +++ b/lib/portManager.ts @@ -0,0 +1,44 @@ +import axios from 'axios'; + +import PortManagerServer from './PortManagerServer'; +import { detectPort } from '../utils/detectPort'; +import { PORT_MANAGER_SERVER_PORT } from '../constants/ports'; + +const BASE_URL = `localhost:${PORT_MANAGER_SERVER_PORT}`; + +async function isPortManagerServerRunning(): Promise { + const port = await detectPort(PORT_MANAGER_SERVER_PORT); + return port === PORT_MANAGER_SERVER_PORT; +} + +export async function startPortManagerServer(): Promise { + const isRunning = await isPortManagerServerRunning(); + + if (!isRunning) { + PortManagerServer.init(); + } +} + +export async function stopPortManagerServer(): Promise { + const isRunning = await isPortManagerServerRunning(); + + if (isRunning) { + await axios.post(`${BASE_URL}/close`); + } +} + +export async function assignPortToServerInstance( + serverInstanceId: string +): Promise { + const { data } = await axios.post(`${BASE_URL}/servers`, { + instanceId: serverInstanceId, + }); + + return data.port; +} + +export async function deleteServerInstance( + serverInstanceId: string +): Promise { + await axios.post(`${BASE_URL}/servers/${serverInstanceId}`); +} From 75726b0775c3314d747142dd7de7c4f30b4ed7fa Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 27 Sep 2023 14:05:12 -0400 Subject: [PATCH 07/23] export port manager --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 00b69c22..a6d97148 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,8 @@ "./constants": "./constants/index.js", "./github": "./lib/github.js", "./ignoreRules": "./lib/ignoreRules.js", - "./path": "./lib/path.js" + "./path": "./lib/path.js", + "./portManager": "./lib/portManager.js" }, "dependencies": { "@types/express": "^4.17.18", From 5766ea78a4fd0d8f41ac08f690d0b39dcb7c3dea Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 27 Sep 2023 14:34:06 -0400 Subject: [PATCH 08/23] rename some things and add server index route --- lib/PortManagerServer.ts | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index 85290cee..5ff1bcac 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -8,19 +8,17 @@ import { PORT_MANAGER_SERVER_PORT, } from '../constants/ports'; -type PortMap = { +type ServerPortMap = { [instanceId: string]: number; }; class PortManagerServer { app?: Express; server?: Server; - ports: PortMap; + serverPortMap: ServerPortMap; constructor() { - this.ports = { - yaa: 6000, - }; + this.serverPortMap = {}; } init(): void { @@ -40,14 +38,15 @@ class PortManagerServer { return; } - this.app.get('/servers/:instanceId', this.getPortByInstanceId); + this.app.get('/servers', this.getServers); + this.app.get('/servers/:instanceId', this.getServerPortByInstanceId); this.app.post('/servers', this.assignPortToServer); this.app.delete('/servers/:instanceId', this.deleteServerInstance); this.app.post('/close', this.closeServer); } setPort(instanceId: string, port: number) { - this.ports[instanceId] = port; + this.serverPortMap[instanceId] = port; } send404(res: Response, instanceId: string) { @@ -56,9 +55,16 @@ class PortManagerServer { .send(`Could not find a server with instanceId ${instanceId}`); } - getPortByInstanceId = (req: Request, res: Response): void => { + getServers = async (req: Request, res: Response): Promise => { + res.send({ + servers: this.serverPortMap, + count: Object.keys(this.serverPortMap.length), + }); + }; + + getServerPortByInstanceId = (req: Request, res: Response): void => { const { instanceId } = req.params; - const port = this.ports[instanceId]; + const port = this.serverPortMap[instanceId]; if (port) { res.send({ port }); @@ -70,7 +76,7 @@ class PortManagerServer { assignPortToServer = async (req: Request, res: Response): Promise => { const { instanceId, port } = req.body; - if (this.ports[instanceId]) { + if (this.serverPortMap[instanceId]) { res .status(409) .send('This server instance has already been assigned a port'); @@ -88,10 +94,10 @@ class PortManagerServer { deleteServerInstance = (req: Request, res: Response): void => { const { instanceId } = req.params; - const port = this.ports[instanceId]; + const port = this.serverPortMap[instanceId]; if (port) { - delete this.ports[instanceId]; + delete this.serverPortMap[instanceId]; res.send(200); } else { this.send404(res, instanceId); From c2e30131e7fbd5470cd35a88fea147ba7456b47e Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Thu, 28 Sep 2023 15:33:01 -0400 Subject: [PATCH 09/23] Fix some portmanager bugs --- lib/PortManagerServer.ts | 14 ++++++-------- lib/portManager.ts | 7 ++++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index 5ff1bcac..1f7a2298 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -80,16 +80,14 @@ class PortManagerServer { res .status(409) .send('This server instance has already been assigned a port'); - } - - if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { + } else if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { res.status(400).send('Port must be between 1024 and 65535'); - } - - const portToUse = await detectPort(port); - this.setPort(instanceId, portToUse); + } else { + const portToUse = await detectPort(port); + this.setPort(instanceId, portToUse); - res.send({ port: portToUse }); + res.send({ port: portToUse }); + } }; deleteServerInstance = (req: Request, res: Response): void => { diff --git a/lib/portManager.ts b/lib/portManager.ts index e33fe5c1..5879b512 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -8,7 +8,7 @@ const BASE_URL = `localhost:${PORT_MANAGER_SERVER_PORT}`; async function isPortManagerServerRunning(): Promise { const port = await detectPort(PORT_MANAGER_SERVER_PORT); - return port === PORT_MANAGER_SERVER_PORT; + return port !== PORT_MANAGER_SERVER_PORT; } export async function startPortManagerServer(): Promise { @@ -42,3 +42,8 @@ export async function deleteServerInstance( ): Promise { await axios.post(`${BASE_URL}/servers/${serverInstanceId}`); } + +export async function hasActiveServers() { + const { data } = await axios.get(`${BASE_URL}/servers`); + return data.count > 0; +} From 060b9f6253df6bf6543f4765fce4ac23b782dcc8 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Thu, 28 Sep 2023 17:31:01 -0400 Subject: [PATCH 10/23] Fix some port manager bugs --- lib/PortManagerServer.ts | 2 +- lib/portManager.ts | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index 1f7a2298..2931dfde 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -58,7 +58,7 @@ class PortManagerServer { getServers = async (req: Request, res: Response): Promise => { res.send({ servers: this.serverPortMap, - count: Object.keys(this.serverPortMap.length), + count: Object.keys(this.serverPortMap).length, }); }; diff --git a/lib/portManager.ts b/lib/portManager.ts index 5879b512..53097c21 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -4,7 +4,7 @@ import PortManagerServer from './PortManagerServer'; import { detectPort } from '../utils/detectPort'; import { PORT_MANAGER_SERVER_PORT } from '../constants/ports'; -const BASE_URL = `localhost:${PORT_MANAGER_SERVER_PORT}`; +const BASE_URL = `http://localhost:${PORT_MANAGER_SERVER_PORT}`; async function isPortManagerServerRunning(): Promise { const port = await detectPort(PORT_MANAGER_SERVER_PORT); @@ -43,7 +43,15 @@ export async function deleteServerInstance( await axios.post(`${BASE_URL}/servers/${serverInstanceId}`); } -export async function hasActiveServers() { +export async function portManagerHasActiveServers() { const { data } = await axios.get(`${BASE_URL}/servers`); return data.count > 0; } + +function toId(str: string) { + return str.replace(/\s+/g, '-').toLowerCase(); +} + +export function getServerInstanceId(serverId: string, resourceId: string) { + return `${toId(serverId)}__${toId(resourceId)}`; +} From d5ce5cd7886ad4030009de207405d7f0760b2bea Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 3 Oct 2023 17:42:39 -0400 Subject: [PATCH 11/23] use cors --- lib/PortManagerServer.ts | 2 ++ package.json | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/PortManagerServer.ts b/lib/PortManagerServer.ts index 2931dfde..ec051318 100644 --- a/lib/PortManagerServer.ts +++ b/lib/PortManagerServer.ts @@ -1,5 +1,6 @@ import express, { Express, Request, Response } from 'express'; import { Server } from 'http'; +import cors from 'cors'; import { detectPort } from '../utils/detectPort'; import { @@ -27,6 +28,7 @@ class PortManagerServer { } this.app = express(); this.app.use(express.json()); + this.app.use(cors()); this.setupRoutes(); this.server = this.app.listen(PORT_MANAGER_SERVER_PORT, () => console.log('Running port manager') diff --git a/package.json b/package.json index a6d97148..29d8a29f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,9 @@ "license": "Apache-2.0", "devDependencies": { "@types/content-disposition": "^0.5.5", + "@types/cors": "^2.8.14", "@types/debounce": "^1.2.1", + "@types/express": "^4.17.18", "@types/findup-sync": "^4.0.2", "@types/fs-extra": "^11.0.1", "@types/jest": "^29.5.0", @@ -58,11 +60,11 @@ "./portManager": "./lib/portManager.js" }, "dependencies": { - "@types/express": "^4.17.18", "address": "^2.0.1", "axios": "^1.3.5", "chokidar": "^3.5.3", "content-disposition": "^0.5.4", + "cors": "^2.8.5", "express": "^4.18.2", "extract-zip": "^2.0.1", "findup-sync": "^5.0.0", From 61d81d4771e827a713f5f13ba372a37cbb4b05f5 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 4 Oct 2023 13:47:30 -0400 Subject: [PATCH 12/23] Add logging/errors to PortManagerServer --- constants/ports.ts | 2 ++ lang/en.lyaml | 11 +++++++++ lib/portManager.ts | 2 +- {lib => utils}/PortManagerServer.ts | 38 ++++++++++++++++++++++------- 4 files changed, 43 insertions(+), 10 deletions(-) rename {lib => utils}/PortManagerServer.ts (72%) diff --git a/constants/ports.ts b/constants/ports.ts index d0fe422f..b99a0901 100644 --- a/constants/ports.ts +++ b/constants/ports.ts @@ -1,3 +1,5 @@ export const MIN_PORT_NUMBER = 1024; export const MAX_PORT_NUMBER = 65535; + +// TODO: What's a good port for the port manager? export const PORT_MANAGER_SERVER_PORT = 12345; diff --git a/lang/en.lyaml b/lang/en.lyaml index 591844fa..bde6d2ee 100644 --- a/lang/en.lyaml +++ b/lang/en.lyaml @@ -112,6 +112,12 @@ en: creatingPath: "Making {{ path }} if needed" logging: creatingFile: "Creating file at {{ path }}" + utils: + PortManagerServer: + started: "PortManagerServer running on port {{ port }}" + setPort: "Server with instanceId {{ instanceId }} assigned to port {{ port }}" + deletedPort: "Server with instanceId {{ instanceId }} unassigned from port {{ port }}" + close: "PortManagerServer shutting down." errors: archive: extractZip: @@ -175,6 +181,11 @@ en: configIgnore: "Unable to determine if config file is properly ignored by git." notify: filePath: "Unable to notify file '{{ filePath }}'" + PortManagerServer: + duplicateInstance: "Failed to start PortManagerServer. An instance of PortManagerServer is already running." + 404: "Could not find a server with instanceId {{ instanceId }}" + 409: "Failed to assign port. Server with instanceId {{ instanceId }} is already running on port {{ port }}" + 400: "Invalid port requested. Port must be between 1024 and 65535." config: cliConfiguration: noConfigLoaded: "No config loaded." diff --git a/lib/portManager.ts b/lib/portManager.ts index 53097c21..d5531c62 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -1,6 +1,6 @@ import axios from 'axios'; -import PortManagerServer from './PortManagerServer'; +import PortManagerServer from '../utils/PortManagerServer'; import { detectPort } from '../utils/detectPort'; import { PORT_MANAGER_SERVER_PORT } from '../constants/ports'; diff --git a/lib/PortManagerServer.ts b/utils/PortManagerServer.ts similarity index 72% rename from lib/PortManagerServer.ts rename to utils/PortManagerServer.ts index ec051318..4fcc6c62 100644 --- a/lib/PortManagerServer.ts +++ b/utils/PortManagerServer.ts @@ -2,17 +2,22 @@ import express, { Express, Request, Response } from 'express'; import { Server } from 'http'; import cors from 'cors'; -import { detectPort } from '../utils/detectPort'; +import { detectPort } from './detectPort'; import { MIN_PORT_NUMBER, MAX_PORT_NUMBER, PORT_MANAGER_SERVER_PORT, } from '../constants/ports'; +import { throwErrorWithMessage } from '../errors/standardErrors'; +import { debug } from './logger'; +import { i18n } from './lang'; type ServerPortMap = { [instanceId: string]: number; }; +const i18nKey = 'utils.PortManagerServer'; + class PortManagerServer { app?: Express; server?: Server; @@ -24,14 +29,16 @@ class PortManagerServer { init(): void { if (this.app) { - throw new Error('Port manager server is already running'); + throwErrorWithMessage(`${i18nKey}.duplicateInstance`); } this.app = express(); this.app.use(express.json()); this.app.use(cors()); this.setupRoutes(); this.server = this.app.listen(PORT_MANAGER_SERVER_PORT, () => - console.log('Running port manager') + debug(`${i18nKey}.started`, { + port: PORT_MANAGER_SERVER_PORT, + }) ); } @@ -48,13 +55,22 @@ class PortManagerServer { } setPort(instanceId: string, port: number) { + debug(`${i18nKey}.setPort`, { instanceId, port }); this.serverPortMap[instanceId] = port; } + deletePort(instanceId: string) { + debug(`${i18nKey}.deletePort`, { + instanceId, + port: this.serverPortMap[instanceId], + }); + delete this.serverPortMap[instanceId]; + } + send404(res: Response, instanceId: string) { res .status(404) - .send(`Could not find a server with instanceId ${instanceId}`); + .send(i18n(`errors.${i18nKey}.404`, { instanceId: instanceId })); } getServers = async (req: Request, res: Response): Promise => { @@ -79,11 +95,14 @@ class PortManagerServer { const { instanceId, port } = req.body; if (this.serverPortMap[instanceId]) { - res - .status(409) - .send('This server instance has already been assigned a port'); + res.status(409).send( + i18n(`errors.${i18nKey}.409`, { + instanceId, + port: this.serverPortMap[instanceId], + }) + ); } else if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { - res.status(400).send('Port must be between 1024 and 65535'); + res.status(400).send(i18n(`errors.${i18nKey}.400`)); } else { const portToUse = await detectPort(port); this.setPort(instanceId, portToUse); @@ -97,7 +116,7 @@ class PortManagerServer { const port = this.serverPortMap[instanceId]; if (port) { - delete this.serverPortMap[instanceId]; + this.deletePort(instanceId); res.send(200); } else { this.send404(res, instanceId); @@ -106,6 +125,7 @@ class PortManagerServer { closeServer = (req: Request, res: Response): void => { if (this.server) { + debug(`${i18nKey}.close`); res.send(200); this.server.close(); } From 73d05b1983494409a0b713dd63479700b40131ad Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 18 Oct 2023 13:40:25 -0400 Subject: [PATCH 13/23] Wait for PortManagerServer to start --- constants/ports.ts | 2 +- lang/en.lyaml | 1 + lib/portManager.ts | 2 +- utils/PortManagerServer.ts | 37 +++++++++++++++++++++++++++++++------ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/constants/ports.ts b/constants/ports.ts index b99a0901..398071f9 100644 --- a/constants/ports.ts +++ b/constants/ports.ts @@ -2,4 +2,4 @@ export const MIN_PORT_NUMBER = 1024; export const MAX_PORT_NUMBER = 65535; // TODO: What's a good port for the port manager? -export const PORT_MANAGER_SERVER_PORT = 12345; +export const PORT_MANAGER_SERVER_PORT = 8080; diff --git a/lang/en.lyaml b/lang/en.lyaml index 5ab132f0..4193ad3f 100644 --- a/lang/en.lyaml +++ b/lang/en.lyaml @@ -208,6 +208,7 @@ en: notify: filePath: "Unable to notify file '{{ filePath }}'" PortManagerServer: + portInUse: "Failed to start PortManagerServer. Port {{ port }} is already in use." duplicateInstance: "Failed to start PortManagerServer. An instance of PortManagerServer is already running." 404: "Could not find a server with instanceId {{ instanceId }}" 409: "Failed to assign port. Server with instanceId {{ instanceId }} is already running on port {{ port }}" diff --git a/lib/portManager.ts b/lib/portManager.ts index d5531c62..f482e6bd 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -15,7 +15,7 @@ export async function startPortManagerServer(): Promise { const isRunning = await isPortManagerServerRunning(); if (!isRunning) { - PortManagerServer.init(); + await PortManagerServer.init(); } } diff --git a/utils/PortManagerServer.ts b/utils/PortManagerServer.ts index 4fcc6c62..975ab587 100644 --- a/utils/PortManagerServer.ts +++ b/utils/PortManagerServer.ts @@ -11,6 +11,7 @@ import { import { throwErrorWithMessage } from '../errors/standardErrors'; import { debug } from './logger'; import { i18n } from './lang'; +import { BaseError } from '../types/Error'; type ServerPortMap = { [instanceId: string]: number; @@ -27,7 +28,7 @@ class PortManagerServer { this.serverPortMap = {}; } - init(): void { + async init(): Promise { if (this.app) { throwErrorWithMessage(`${i18nKey}.duplicateInstance`); } @@ -35,11 +36,35 @@ class PortManagerServer { this.app.use(express.json()); this.app.use(cors()); this.setupRoutes(); - this.server = this.app.listen(PORT_MANAGER_SERVER_PORT, () => - debug(`${i18nKey}.started`, { - port: PORT_MANAGER_SERVER_PORT, - }) - ); + + try { + this.server = await this.listen(); + } catch (e) { + const error = e as BaseError; + if (error.code === 'EADDRINUSE') { + throwErrorWithMessage( + `${i18n}.portInUse`, + { + port: PORT_MANAGER_SERVER_PORT, + }, + error + ); + } + throw error; + } + } + + listen(): Promise { + return new Promise((resolve, reject) => { + const server = this.app!.listen(PORT_MANAGER_SERVER_PORT, () => { + debug(`${i18nKey}.started`, { + port: PORT_MANAGER_SERVER_PORT, + }); + resolve(server); + }).on('error', err => { + reject(err); + }); + }); } setupRoutes(): void { From 90ae97869fa49b7678a60916b49a91eea0ec6cbd Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 18 Oct 2023 14:35:53 -0400 Subject: [PATCH 14/23] rename assignPortToServerInstance --- lib/portManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/portManager.ts b/lib/portManager.ts index f482e6bd..ac00354e 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -27,7 +27,7 @@ export async function stopPortManagerServer(): Promise { } } -export async function assignPortToServerInstance( +export async function requestPortForServerInstance( serverInstanceId: string ): Promise { const { data } = await axios.post(`${BASE_URL}/servers`, { From e79df2a8a1ea682b28b72c9605b5f42e92cd44e7 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 18 Oct 2023 16:53:33 -0400 Subject: [PATCH 15/23] Set up port manager for requesting multiple ports --- lib/portManager.ts | 8 +++---- utils/PortManagerServer.ts | 48 ++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/lib/portManager.ts b/lib/portManager.ts index ac00354e..05d34242 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -27,11 +27,11 @@ export async function stopPortManagerServer(): Promise { } } -export async function requestPortForServerInstance( - serverInstanceId: string -): Promise { +export async function requestPorts( + serverInstanceIds: Array +): Promise> { const { data } = await axios.post(`${BASE_URL}/servers`, { - instanceId: serverInstanceId, + instanceIds: serverInstanceIds, }); return data.port; diff --git a/utils/PortManagerServer.ts b/utils/PortManagerServer.ts index 975ab587..e2852ca0 100644 --- a/utils/PortManagerServer.ts +++ b/utils/PortManagerServer.ts @@ -74,7 +74,7 @@ class PortManagerServer { this.app.get('/servers', this.getServers); this.app.get('/servers/:instanceId', this.getServerPortByInstanceId); - this.app.post('/servers', this.assignPortToServer); + this.app.post('/servers', this.assignPortsToServers); this.app.delete('/servers/:instanceId', this.deleteServerInstance); this.app.post('/close', this.closeServer); } @@ -116,24 +116,36 @@ class PortManagerServer { } }; - assignPortToServer = async (req: Request, res: Response): Promise => { - const { instanceId, port } = req.body; - - if (this.serverPortMap[instanceId]) { - res.status(409).send( - i18n(`errors.${i18nKey}.409`, { - instanceId, - port: this.serverPortMap[instanceId], - }) - ); - } else if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { - res.status(400).send(i18n(`errors.${i18nKey}.400`)); - } else { - const portToUse = await detectPort(port); - this.setPort(instanceId, portToUse); + assignPortsToServers = async (req: Request, res: Response): Promise => { + const { instanceIds, port } = req.body; - res.send({ port: portToUse }); - } + const portPromises: Array> = []; + + instanceIds.forEach((instanceId: number) => { + if (this.serverPortMap[instanceId]) { + res.status(409).send( + i18n(`errors.${i18nKey}.409`, { + instanceId, + port: this.serverPortMap[instanceId], + }) + ); + return; + } else if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { + res.status(400).send(i18n(`errors.${i18nKey}.400`)); + return; + } else { + portPromises.push(detectPort(port)); + } + }); + + const ports = await Promise.all(portPromises); + + ports.forEach((port: number, index: number) => { + const instanceId = instanceIds[index]; + this.setPort(instanceId, port); + }); + + res.send({ ports }); }; deleteServerInstance = (req: Request, res: Response): void => { From 1d301476751f6dab978b9d8c21d2d879db164093 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Thu, 19 Oct 2023 15:47:53 -0400 Subject: [PATCH 16/23] fix bug in requestPort --- lib/portManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/portManager.ts b/lib/portManager.ts index 05d34242..30d2a8aa 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -34,7 +34,7 @@ export async function requestPorts( instanceIds: serverInstanceIds, }); - return data.port; + return data.ports; } export async function deleteServerInstance( From 0bb5532dd58ce80bf90fbcb29220e4b843ba0238 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 31 Oct 2023 12:46:03 -0400 Subject: [PATCH 17/23] Update request ports to allow for specifying ports --- lib/portManager.ts | 7 ++++--- package.json | 2 +- types/PortManager.ts | 4 ++++ utils/PortManagerServer.ts | 26 +++++++++++++++++++------- utils/detectPort.ts | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 types/PortManager.ts diff --git a/lib/portManager.ts b/lib/portManager.ts index 30d2a8aa..126f26ad 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -3,6 +3,7 @@ import axios from 'axios'; import PortManagerServer from '../utils/PortManagerServer'; import { detectPort } from '../utils/detectPort'; import { PORT_MANAGER_SERVER_PORT } from '../constants/ports'; +import { RequestPortsData } from '../types/PortManager'; const BASE_URL = `http://localhost:${PORT_MANAGER_SERVER_PORT}`; @@ -28,10 +29,10 @@ export async function stopPortManagerServer(): Promise { } export async function requestPorts( - serverInstanceIds: Array -): Promise> { + portData: Array +): Promise> { const { data } = await axios.post(`${BASE_URL}/servers`, { - instanceIds: serverInstanceIds, + portData: portData, }); return data.ports; diff --git a/package.json b/package.json index 0a47a82d..c84c7864 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/content-disposition": "^0.5.5", - "@types/cors": "^2.8.14", + "@types/cors": "^2.8.15", "@types/debounce": "^1.2.1", "@types/express": "^4.17.18", "@types/findup-sync": "^4.0.2", diff --git a/types/PortManager.ts b/types/PortManager.ts new file mode 100644 index 00000000..a319a031 --- /dev/null +++ b/types/PortManager.ts @@ -0,0 +1,4 @@ +export type RequestPortsData = { + instanceId: string; + port?: number; +}; diff --git a/utils/PortManagerServer.ts b/utils/PortManagerServer.ts index e2852ca0..2c3f21ba 100644 --- a/utils/PortManagerServer.ts +++ b/utils/PortManagerServer.ts @@ -12,6 +12,7 @@ import { throwErrorWithMessage } from '../errors/standardErrors'; import { debug } from './logger'; import { i18n } from './lang'; import { BaseError } from '../types/Error'; +import { RequestPortsData } from '../types/PortManager'; type ServerPortMap = { [instanceId: string]: number; @@ -116,12 +117,16 @@ class PortManagerServer { } }; - assignPortsToServers = async (req: Request, res: Response): Promise => { - const { instanceIds, port } = req.body; + assignPortsToServers = async ( + req: Request }>, + res: Response + ): Promise => { + const { portData } = req.body; - const portPromises: Array> = []; + const portPromises: Array>> = []; - instanceIds.forEach((instanceId: number) => { + portData.forEach(data => { + const { port, instanceId } = data; if (this.serverPortMap[instanceId]) { res.status(409).send( i18n(`errors.${i18nKey}.409`, { @@ -134,14 +139,21 @@ class PortManagerServer { res.status(400).send(i18n(`errors.${i18nKey}.400`)); return; } else { - portPromises.push(detectPort(port)); + const promise = new Promise>(resolve => { + detectPort(port).then(resolvedPort => { + resolve({ + instanceId, + port: resolvedPort, + }); + }); + }); + portPromises.push(promise); } }); const ports = await Promise.all(portPromises); - ports.forEach((port: number, index: number) => { - const instanceId = instanceIds[index]; + ports.forEach(({ port, instanceId }) => { this.setPort(instanceId, port); }); diff --git a/utils/detectPort.ts b/utils/detectPort.ts index ab62cf4a..1c968c70 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -9,7 +9,7 @@ type NetError = Error & { type ListenCallback = (error: NetError | null, port: number) => void; -export function detectPort(port: number | null): Promise { +export function detectPort(port?: number | null): Promise { if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { throw new Error('Port must be between 1024 and 65535'); } From d191ff39aaccd52278d37276e31f484eb70bc714 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 31 Oct 2023 15:37:55 -0400 Subject: [PATCH 18/23] port manager api tweaks --- lib/portManager.ts | 8 ++++++-- types/PortManager.ts | 4 ---- utils/PortManagerServer.ts | 26 ++++++++++++++------------ 3 files changed, 20 insertions(+), 18 deletions(-) delete mode 100644 types/PortManager.ts diff --git a/lib/portManager.ts b/lib/portManager.ts index 126f26ad..7d9eed46 100644 --- a/lib/portManager.ts +++ b/lib/portManager.ts @@ -3,7 +3,6 @@ import axios from 'axios'; import PortManagerServer from '../utils/PortManagerServer'; import { detectPort } from '../utils/detectPort'; import { PORT_MANAGER_SERVER_PORT } from '../constants/ports'; -import { RequestPortsData } from '../types/PortManager'; const BASE_URL = `http://localhost:${PORT_MANAGER_SERVER_PORT}`; @@ -28,9 +27,14 @@ export async function stopPortManagerServer(): Promise { } } +type RequestPortsData = { + instanceId: string; + port?: number; +}; + export async function requestPorts( portData: Array -): Promise> { +): Promise<{ [instanceId: string]: number }> { const { data } = await axios.post(`${BASE_URL}/servers`, { portData: portData, }); diff --git a/types/PortManager.ts b/types/PortManager.ts deleted file mode 100644 index a319a031..00000000 --- a/types/PortManager.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type RequestPortsData = { - instanceId: string; - port?: number; -}; diff --git a/utils/PortManagerServer.ts b/utils/PortManagerServer.ts index 2c3f21ba..ffad2727 100644 --- a/utils/PortManagerServer.ts +++ b/utils/PortManagerServer.ts @@ -123,7 +123,7 @@ class PortManagerServer { ): Promise => { const { portData } = req.body; - const portPromises: Array>> = []; + const portPromises: Array> = []; portData.forEach(data => { const { port, instanceId } = data; @@ -139,23 +139,25 @@ class PortManagerServer { res.status(400).send(i18n(`errors.${i18nKey}.400`)); return; } else { - const promise = new Promise>(resolve => { - detectPort(port).then(resolvedPort => { - resolve({ - instanceId, - port: resolvedPort, + const promise = new Promise<{ [instanceId: string]: number }>( + resolve => { + detectPort(port).then(resolvedPort => { + resolve({ + [instanceId]: resolvedPort, + }); }); - }); - }); + } + ); portPromises.push(promise); } }); - const ports = await Promise.all(portPromises); + const portList = await Promise.all(portPromises); + const ports = portList.reduce((a, c) => Object.assign(a, c)); - ports.forEach(({ port, instanceId }) => { - this.setPort(instanceId, port); - }); + for (const instanceId in ports) { + this.setPort(instanceId, ports[instanceId]); + } res.send({ ports }); }; From 872304ff68eb45562e02664b2ec1a48e646c045e Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 7 Nov 2023 16:00:13 -0500 Subject: [PATCH 19/23] remove todo --- constants/ports.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/constants/ports.ts b/constants/ports.ts index 398071f9..b1288985 100644 --- a/constants/ports.ts +++ b/constants/ports.ts @@ -1,5 +1,4 @@ export const MIN_PORT_NUMBER = 1024; export const MAX_PORT_NUMBER = 65535; -// TODO: What's a good port for the port manager? export const PORT_MANAGER_SERVER_PORT = 8080; From 2726eec66b8a99f2ea482a437ef916aa915219ba Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Tue, 7 Nov 2023 16:01:53 -0500 Subject: [PATCH 20/23] restore portmanager types file --- types/PortManager.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 types/PortManager.ts diff --git a/types/PortManager.ts b/types/PortManager.ts new file mode 100644 index 00000000..a319a031 --- /dev/null +++ b/types/PortManager.ts @@ -0,0 +1,4 @@ +export type RequestPortsData = { + instanceId: string; + port?: number; +}; From 25eb5eaef3ea7a0b33101476d4fff018154283c5 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 8 Nov 2023 10:49:48 -0500 Subject: [PATCH 21/23] Add detectPort copy to lang file --- lang/en.json | 5 +++++ utils/detectPort.ts | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lang/en.json b/lang/en.json index 47259934..d6762f00 100644 --- a/lang/en.json +++ b/lang/en.json @@ -322,6 +322,11 @@ "throwInvalidPathInput": "Expected Path Input" } }, + "detectPort": { + "errors": { + "invalidPort": "Port must be between 1024 and 65535" + } + }, "PortManagerServer": { "started": "PortManagerServer running on port {{ port }}", "setPort": "Server with instanceId {{ instanceId }} assigned to port {{ port }}", diff --git a/utils/detectPort.ts b/utils/detectPort.ts index 1c968c70..1af3f649 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -1,5 +1,6 @@ import net, { AddressInfo } from 'net'; import { ip } from 'address'; +import { throwErrorWithMessage } from '../errors/standardErrors'; import { MIN_PORT_NUMBER, MAX_PORT_NUMBER } from '../constants/ports'; @@ -9,9 +10,11 @@ type NetError = Error & { type ListenCallback = (error: NetError | null, port: number) => void; +const i18nKey = 'utils.detectPort'; + export function detectPort(port?: number | null): Promise { if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { - throw new Error('Port must be between 1024 and 65535'); + throwErrorWithMessage(`${i18nKey}.errors.invalidPort`); } const portToUse = port || 0; From 825d86b48b26a205ee518a34e48e9de6548787a2 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 8 Nov 2023 11:19:42 -0500 Subject: [PATCH 22/23] Add detect port license --- utils/detectPort.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/utils/detectPort.ts b/utils/detectPort.ts index 1af3f649..ac48671e 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -1,3 +1,28 @@ +/* +From https://github.com/node-modules/detect-port/tree/master + +The MIT License (MIT) + +Copyright (c) 2014 - present node-modules and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + import net, { AddressInfo } from 'net'; import { ip } from 'address'; import { throwErrorWithMessage } from '../errors/standardErrors'; From bd1e9cb755018e99420513bdc61be79099359991 Mon Sep 17 00:00:00 2001 From: Camden Phalen Date: Wed, 8 Nov 2023 11:25:48 -0500 Subject: [PATCH 23/23] update invalid port copy --- lang/en.json | 4 ++-- utils/PortManagerServer.ts | 7 ++++++- utils/detectPort.ts | 5 ++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lang/en.json b/lang/en.json index d6762f00..d0e60bdc 100644 --- a/lang/en.json +++ b/lang/en.json @@ -324,7 +324,7 @@ }, "detectPort": { "errors": { - "invalidPort": "Port must be between 1024 and 65535" + "invalidPort": "Port must be between {{ minPort }} and {{ maxPort }}" } }, "PortManagerServer": { @@ -337,7 +337,7 @@ "duplicateInstance": "Failed to start PortManagerServer. An instance of PortManagerServer is already running.", "404": "Could not find a server with instanceId {{ instanceId }}", "409": "Failed to assign port. Server with instanceId {{ instanceId }} is already running on port {{ port }}", - "400": "Invalid port requested. Port must be between 1024 and 65535." + "400": "Invalid port requested. Port must be between {{ minPort }} and {{ maxPort }}." } } }, diff --git a/utils/PortManagerServer.ts b/utils/PortManagerServer.ts index 7b0c9597..53f60bc5 100644 --- a/utils/PortManagerServer.ts +++ b/utils/PortManagerServer.ts @@ -136,7 +136,12 @@ class PortManagerServer { ); return; } else if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { - res.status(400).send(i18n(`${i18nKey}.errors.400`)); + res.status(400).send( + i18n(`${i18nKey}.errors.400`, { + minPort: MIN_PORT_NUMBER, + maxPort: MAX_PORT_NUMBER, + }) + ); return; } else { const promise = new Promise<{ [instanceId: string]: number }>( diff --git a/utils/detectPort.ts b/utils/detectPort.ts index ac48671e..24a94822 100644 --- a/utils/detectPort.ts +++ b/utils/detectPort.ts @@ -39,7 +39,10 @@ const i18nKey = 'utils.detectPort'; export function detectPort(port?: number | null): Promise { if (port && (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER)) { - throwErrorWithMessage(`${i18nKey}.errors.invalidPort`); + throwErrorWithMessage(`${i18nKey}.errors.invalidPort`, { + minPort: MIN_PORT_NUMBER, + maxPort: MAX_PORT_NUMBER, + }); } const portToUse = port || 0;