From 7af06303911710bbb9869b881daf0ef9781ba044 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Fri, 23 May 2025 13:10:04 +0200 Subject: [PATCH] chore: restart web server when ports in config have changed --- src/index.ts | 27 ++---------- src/services/configWatcherService.ts | 7 +++ src/services/webService.ts | 65 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 src/services/webService.ts diff --git a/src/index.ts b/src/index.ts index f688b9e1..80adc252 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,12 +12,10 @@ import { logger } from "@/src/utils/logger"; logger.info("Starting up..."); // Proceed with normal startup: bring up config watcher service, validate config, connect to MongoDB, and finally start listening for HTTP. -import http from "http"; -import https from "https"; -import fs from "node:fs"; -import { app } from "./app"; import mongoose from "mongoose"; import { JSONStringify } from "json-with-bigint"; +import { startWebServer } from "./services/webService"; + import { validateConfig } from "@/src/services/configWatcherService"; // Patch JSON.stringify to work flawlessly with Bigints. @@ -29,26 +27,7 @@ mongoose .connect(config.mongodbUrl) .then(() => { logger.info("Connected to MongoDB"); - - const httpPort = config.httpPort || 80; - const httpsPort = config.httpsPort || 443; - const options = { - key: fs.readFileSync("static/certs/key.pem"), - cert: fs.readFileSync("static/certs/cert.pem") - }; - - // eslint-disable-next-line @typescript-eslint/no-misused-promises - http.createServer(app).listen(httpPort, () => { - logger.info("HTTP server started on port " + httpPort); - // eslint-disable-next-line @typescript-eslint/no-misused-promises - https.createServer(options, app).listen(httpsPort, () => { - logger.info("HTTPS server started on port " + httpsPort); - - logger.info( - "Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort) - ); - }); - }); + startWebServer(); }) .catch(error => { if (error instanceof Error) { diff --git a/src/services/configWatcherService.ts b/src/services/configWatcherService.ts index e8584785..46c236ea 100644 --- a/src/services/configWatcherService.ts +++ b/src/services/configWatcherService.ts @@ -2,6 +2,7 @@ import fs from "fs"; import fsPromises from "fs/promises"; import { logger } from "../utils/logger"; import { config, configPath, loadConfig } from "./configService"; +import { getWebPorts, startWebServer, stopWebServer } from "./webService"; let amnesia = false; fs.watchFile(configPath, () => { @@ -16,6 +17,12 @@ fs.watchFile(configPath, () => { process.exit(1); } validateConfig(); + + const webPorts = getWebPorts(); + if (config.httpPort != webPorts.http || config.httpsPort != webPorts.https) { + logger.info(`Restarting web server to apply port changes.`); + void stopWebServer().then(startWebServer); + } } }); diff --git a/src/services/webService.ts b/src/services/webService.ts new file mode 100644 index 00000000..77fe01fe --- /dev/null +++ b/src/services/webService.ts @@ -0,0 +1,65 @@ +import http from "http"; +import https from "https"; +import fs from "node:fs"; +import { config } from "./configService"; +import { logger } from "../utils/logger"; +import { app } from "../app"; +import { AddressInfo } from "node:net"; + +let httpServer: http.Server | undefined; +let httpsServer: https.Server | undefined; + +const tlsOptions = { + key: fs.readFileSync("static/certs/key.pem"), + cert: fs.readFileSync("static/certs/cert.pem") +}; + +export const startWebServer = (): void => { + const httpPort = config.httpPort || 80; + const httpsPort = config.httpsPort || 443; + + // eslint-disable-next-line @typescript-eslint/no-misused-promises + httpServer = http.createServer(app); + httpServer.listen(httpPort, () => { + logger.info("HTTP server started on port " + httpPort); + // eslint-disable-next-line @typescript-eslint/no-misused-promises + httpsServer = https.createServer(tlsOptions, app); + httpsServer.listen(httpsPort, () => { + logger.info("HTTPS server started on port " + httpsPort); + + logger.info( + "Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort) + ); + }); + }); +}; + +export const getWebPorts = (): Record<"http" | "https", number | undefined> => { + return { + http: (httpServer?.address() as AddressInfo | undefined)?.port, + https: (httpsServer?.address() as AddressInfo | undefined)?.port + }; +}; + +export const stopWebServer = async (): Promise => { + const promises: Promise[] = []; + if (httpServer) { + promises.push( + new Promise(resolve => { + httpServer!.close(() => { + resolve(); + }); + }) + ); + } + if (httpsServer) { + promises.push( + new Promise(resolve => { + httpsServer!.close(() => { + resolve(); + }); + }) + ); + } + await Promise.all(promises); +}; -- 2.47.2