feedback5 R1: startServer and main become wiring — PORT / HOST / TRUST_PROXY and the option picks go to http/config.js, the session stack and the /ws upgrade to http/websocket.js, the request listener and /healthz to http/routes.js (new), the security headers and the clientError 400 to http/common.js, the banner, signals and entry check to http/boot.js
Same order of construction, listeners and headers as before; a scripted fingerprint (export list, 51 HTTP requests' status / header order / body hash, raw upgrade and malformed-request replies) and the process run (banner, port in use, SIGINT) match the pre-split server exactly. test/version.test.js reads the banner and /healthz from their new files; module headers describe each piece.
This commit is contained in:
1 parent
b48a67caec
commit
1b38e30819
11 files changed
+323
-202
No files matched your search
+60
-1
@@ -1,6 +1,16 @@
|
||||
// server/http/boot.js — what the process prints when it boots (moved from server/index.js).
|
||||
// server/http/boot.js — running the server as a process (`node server/index.js`, npm start, scripts/launch.mjs):
|
||||
//
|
||||
// * the boot banner: release version, the Local URL, the LAN URLs when listening on every interface, the
|
||||
// cloudflared command for internet play;
|
||||
// * a server that cannot start exits 1 (with a hint when the port is in use); unhandled rejections and uncaught
|
||||
// exceptions are logged, not fatal;
|
||||
// * graceful shutdown on SIGINT/SIGTERM (rooms get room.closed{reason:'shutdown'}, sockets close 1001); a second
|
||||
// signal exits at once, and the process exits anyway 5 s after the first.
|
||||
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { APP_VERSION } from '../../shared/constants.js';
|
||||
|
||||
/** Non-internal IPv4 addresses as http URLs. @param {number} port */
|
||||
export function lanUrls(port) {
|
||||
@@ -12,3 +22,52 @@ export function lanUrls(port) {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Is the module whose `import.meta.url` is `metaUrl` the file node was started with? */
|
||||
export function isProcessEntry(metaUrl) {
|
||||
if (!process.argv[1]) return false;
|
||||
try {
|
||||
return fs.realpathSync(process.argv[1]) === fs.realpathSync(fileURLToPath(metaUrl));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Print the boot banner of a started server. @param {{ url: string, host: string, port: number }} srv */
|
||||
export function printBanner(srv) {
|
||||
console.log(`\n 卫戍协议:盟约 · Stronghold Protocol: Alliance v${APP_VERSION}`);
|
||||
console.log(` Local: ${srv.url}`);
|
||||
if (srv.host === '0.0.0.0' || srv.host === '::') {
|
||||
for (const u of lanUrls(srv.port)) console.log(` LAN: ${u}`);
|
||||
}
|
||||
console.log(' Internet: cloudflared tunnel --url ' + `http://localhost:${srv.port}` + '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* The process main: start the server, print the banner, stop gracefully on SIGINT / SIGTERM.
|
||||
* @param {() => Promise<{ url: string, host: string, port: number, close: () => Promise<void> }>} start index.js startServer
|
||||
*/
|
||||
export async function runMain(start) {
|
||||
process.on('unhandledRejection', (e) => console.error('[process] unhandled rejection', e));
|
||||
process.on('uncaughtException', (e) => console.error('[process] uncaught exception', e));
|
||||
let srv;
|
||||
try {
|
||||
srv = await start();
|
||||
} catch (e) {
|
||||
if (e && e.code === 'EADDRINUSE') console.error(`端口已被占用 / port in use: ${e.port ?? process.env.PORT ?? 3000}. Try PORT=3001 npm start`);
|
||||
else console.error('[boot] failed to start', e);
|
||||
process.exit(1);
|
||||
}
|
||||
printBanner(srv);
|
||||
|
||||
let stopping = false;
|
||||
const stop = (signal) => {
|
||||
if (stopping) { console.log('forced exit'); process.exit(1); }
|
||||
stopping = true;
|
||||
console.log(`\n[${signal}] shutting down…`);
|
||||
setTimeout(() => process.exit(0), 5000).unref();
|
||||
srv.close().then(() => process.exit(0), () => process.exit(1));
|
||||
};
|
||||
process.on('SIGINT', () => stop('SIGINT'));
|
||||
process.on('SIGTERM', () => stop('SIGTERM'));
|
||||
}
|
||||
Reference in new issue
Block a user