Validate SSL config for sanity before startup
| @@ -190,13 +190,46 @@ export class ServerStartup { | ||
| 190 | 190 | } |
| 191 | 191 | |
| 192 | 192 | /** |
| 193 | + * Prints a fatal error message and exits the process. | |
| 194 | + * @param {string} message | |
| 195 | + */ | |
| 196 | + #fatal(message) { | |
| 197 | + console.error(color.red(message)); | |
| 198 | + process.exit(1); | |
| 199 | + } | |
| 200 | + | |
| 201 | + /** | |
| 202 | + * Checks if SSL options are valid. If not, it will print an error message and exit the process. | |
| 203 | + * @returns {void} | |
| 204 | + */ | |
| 205 | + #verifySslOptions() { | |
| 206 | + if (!this.cliArgs.ssl) return; | |
| 207 | + | |
| 208 | + if (!this.cliArgs.certPath) { | |
| 209 | + this.#fatal('Error: SSL certificate path is required when using HTTPS. Check your config'); | |
| 210 | + } | |
| 211 | + | |
| 212 | + if (!this.cliArgs.keyPath) { | |
| 213 | + this.#fatal('Error: SSL key path is required when using HTTPS. Check your config'); | |
| 214 | + } | |
| 215 | + | |
| 216 | + if (!fs.existsSync(this.cliArgs.certPath)) { | |
| 217 | + this.#fatal('Error: SSL certificate path does not exist'); | |
| 218 | + } | |
| 219 | + | |
| 220 | + if (!fs.existsSync(this.cliArgs.keyPath)) { | |
| 221 | + this.#fatal('Error: SSL key path does not exist'); | |
| 222 | + } | |
| 223 | + } | |
| 224 | + | |
| 225 | + /** | |
| 193 | 226 | * Creates an HTTPS server. |
| 194 | 227 | * @param {URL} url The URL to listen on |
| 195 | 228 | * @param {number} ipVersion the ip version to use |
| 196 | 229 | * @returns {Promise<void>} A promise that resolves when the server is listening |
| 197 | - * @throws {Error} If the server fails to start | |
| 198 | 230 | */ |
| 199 | 231 | #createHttpsServer(url, ipVersion) { |
| 232 | + this.#verifySslOptions(); | |
| 200 | 233 | return new Promise((resolve, reject) => { |
| 201 | 234 | const sslOptions = { |
| 202 | 235 | cert: fs.readFileSync(this.cliArgs.certPath), |
| @@ -222,7 +255,6 @@ export class ServerStartup { | ||
| 222 | 255 | * @param {URL} url The URL to listen on |
| 223 | 256 | * @param {number} ipVersion the ip version to use |
| 224 | 257 | * @returns {Promise<void>} A promise that resolves when the server is listening |
| 225 | - * @throws {Error} If the server fails to start | |
| 226 | 258 | */ |
| 227 | 259 | #createHttpServer(url, ipVersion) { |
| 228 | 260 | return new Promise((resolve, reject) => { |
| @@ -257,7 +289,7 @@ export class ServerStartup { | ||
| 257 | 289 | try { |
| 258 | 290 | await createFunc(this.cliArgs.getIPv6ListenUrl(), 6); |
| 259 | 291 | } catch (error) { |
| 260 | 292 | console.error('non-fatal errorWarning: failed to start server on IPv6'); |
| 261 | 293 | console.error(error); |
| 262 | 294 | |
| 263 | 295 | v6Failed = true; |
| @@ -268,7 +300,7 @@ export class ServerStartup { | ||
| 268 | 300 | try { |
| 269 | 301 | await createFunc(this.cliArgs.getIPv4ListenUrl(), 4); |
| 270 | 302 | } catch (error) { |
| 271 | 303 | console.error('non-fatal errorWarning: failed to start server on IPv4'); |
| 272 | 304 | console.error(error); |
| 273 | 305 | |
| 274 | 306 | v4Failed = true; |
| @@ -285,18 +317,15 @@ export class ServerStartup { | ||
| 285 | 317 | */ |
| 286 | 318 | #handleServerListenFail({ v6Failed, v4Failed, useIPv6, useIPv4 }) { |
| 287 | 319 | if (v6Failed && !useIPv4) { |
| 288 | 320 | console.error(colorthis.red#fatal('fatal errorError: Failed to start server on IPv6 and IPv4 disabled')); |
| 289 | - process.exit(1); | |
| 290 | 321 | } |
| 291 | 322 | |
| 292 | 323 | if (v4Failed && !useIPv6) { |
| 293 | 324 | console.error(colorthis.red#fatal('fatal errorError: Failed to start server on IPv4 and IPv6 disabled')); |
| 294 | - process.exit(1); | |
| 295 | 325 | } |
| 296 | 326 | |
| 297 | 327 | if (v6Failed && v4Failed) { |
| 298 | 328 | console.error(colorthis.red#fatal('fatal errorError: Failed to start server on both IPv6 and IPv4')); |
| 299 | - process.exit(1); | |
| 300 | 329 | } |
| 301 | 330 | } |
| 302 | 331 | |