Cleaned up HttpServer. WebSocket connects

This commit is contained in:
2025-09-28 11:19:15 -04:00
parent 8585549ae1
commit 9306632cc1
3 changed files with 54 additions and 30 deletions

View File

@@ -3,22 +3,44 @@ import {LoggerFactory} from '@techniker-me/logger';
import HttpServer from './net/http/HttpServer'; import HttpServer from './net/http/HttpServer';
import HealthCheckRoute from './health/HealthCheckRoute'; import HealthCheckRoute from './health/HealthCheckRoute';
import HealthCheck from './health/HealthCheck'; import HealthCheck from './health/HealthCheck';
import WebSocketServer from './net/websocket/WebSocketServer';
const logger = LoggerFactory.getLogger('Server'); const logger = LoggerFactory.getLogger('Server');
const healthCheck = new HealthCheck(); const healthCheck = new HealthCheck();
const healthCheckRoute = new HealthCheckRoute(healthCheck); const healthCheckRoute = new HealthCheckRoute(healthCheck);
const httpServer = new HttpServer('http', 3000, healthCheckRoute, {}, '', [], path.resolve(process.cwd(), 'assets', 'favicon', 'favicon.ico'), {}); const httpServer = new HttpServer('http', 3000, healthCheckRoute, {}, '', [], path.resolve(process.cwd(), 'assets', 'favicon', 'favicon.ico'), {});
httpServer.on('error', () => logger.error('[HttpServer] Error'));
httpServer.on('error', () => { function connectDelegate(connection: ExtendedWebSocket, req: IncomingMessage) {
console.log('[HttpServer] Error event'); console.log('[Server] Connect delegate');
logger.error('[HttpServer] Error'); }
});
httpServer.on('request', (method: string, url: string, statusCode: number, headers: Record<string, string>) => { function requestDelegate(connection: ExtendedWebSocket, message: Buffer) {
console.log(`[HttpServer] Request: ${method} ${url} -> ${statusCode}`); console.log('[Server] Request delegate');
}); }
function disconnectDelegate(connection: ExtendedWebSocket, reasonCode: number, description: string) {
console.log('[Server] Disconnect delegate');
}
function pongDelegate(connection: ExtendedWebSocket, message: Buffer) {
console.log('[Server] Pong delegate');
}
httpServer httpServer
.start() .start()
.then(() => console.log('[Server] Server started successfully')) .then(() => {
.catch(err => console.log('[Server] Server failed to start:', err)); const server = httpServer.getServer();
if (server) {
const websocketServer = new WebSocketServer(server, {path: '/ws'});
websocketServer.start(connectDelegate, requestDelegate, disconnectDelegate, pongDelegate);
} else {
console.error('[Server] Failed to get HTTP server instance');
}
})
.catch(err => console.log('[Server] Server failed to start:', err));

View File

@@ -155,6 +155,11 @@ export default class HttpServer {
this._eventEmitter.on(event, handler); this._eventEmitter.on(event, handler);
} }
public getServer(): Nullable<Server> {
return this._server.value;
}
private configureListener() { private configureListener() {
if (!this._app.value) { if (!this._app.value) {
throw new Error('Unable to configure listener, no app instance found'); throw new Error('Unable to configure listener, no app instance found');
@@ -344,13 +349,16 @@ export default class HttpServer {
let catchAllHandler: Nullable<RequestHandler> = null; let catchAllHandler: Nullable<RequestHandler> = null;
const registerRoutes = (routes: Record<string, RequestHandler>): void => { const registerRoutes = (method: string, routes: Record<string, RequestHandler>): void => {
for (const route of Object.entries(routes)) { for (const route of Object.entries(routes)) {
if (!route) {
continue;
}
const [name, handler] = route; const [name, handler] = route;
console.log(`[${name}] registering [%o]`, handler);
if (name === '*') { if (name === '*') {
console.log('Catch-all handler', name, handler);
if (catchAllHandler) { if (catchAllHandler) {
throw new Error(`Only one catch-all handler can ber registered per server, ignoring conflicting catch-all`); throw new Error(`Only one catch-all handler can ber registered per server, ignoring conflicting catch-all`);
} }
@@ -359,21 +367,15 @@ export default class HttpServer {
continue; continue;
} }
this._logger.debug(`Registering [GET] route [${name}] with [%o]`, handler); this._logger.debug(`Registering [${method}] route [${name}] handler`);
app.get(name, handler); app[method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete'](name, handler);
} }
} }
const getRoutes = this._routes.getGETRoutes(); registerRoutes('GET', this._routes.getGETRoutes());
const postRoutes = this._routes.getPOSTRoutes(); registerRoutes('POST', this._routes.getPOSTRoutes());
const putRoutes = this._routes.getPUTRoutes(); registerRoutes('PUT', this._routes.getPUTRoutes());
const patchRoutes = this._routes.getPATCHRoutes(); registerRoutes('PATCH', this._routes.getPATCHRoutes());
const deleteRoutes = this._routes.getDELETERoutes(); registerRoutes('DELETE', this._routes.getDELETERoutes());
registerRoutes(getRoutes);
registerRoutes(postRoutes);
registerRoutes(putRoutes);
registerRoutes(patchRoutes);
registerRoutes(deleteRoutes);
} }
} }

View File

@@ -5,7 +5,6 @@ import ws, {WebSocketServer as WSServer, WebSocket} from 'ws';
import Assert from '../../lang/Assert'; import Assert from '../../lang/Assert';
import Strings from '../../lang/Strings'; import Strings from '../../lang/Strings';
import WebsocketExtensions from 'websocket-extensions'; import WebsocketExtensions from 'websocket-extensions';
import deflate from 'permessage-deflate';
interface ExtendedWebSocket extends WebSocket { interface ExtendedWebSocket extends WebSocket {
id: string; id: string;
@@ -100,11 +99,12 @@ export default class WebSocketServer {
this._server = new WSServer(serverOptions); this._server = new WSServer(serverOptions);
this._extensions = new WebsocketExtensions(); this._extensions = new WebsocketExtensions();
this._extensions.add(deflate()); // this._extensions.add(deflate());
(this._server as WSServer & {_server?: HttpServer})._server = this._httpServer; (this._server as WSServer & {_server?: HttpServer})._server = this._httpServer;
this._httpServer.on('error', this._server.emit.bind(this._server, 'error')); this._httpServer.on('error', this._server.emit.bind(this._server, 'error'));
this._httpServer.on('listening', this._server.emit.bind(this._server, 'listening')); this._httpServer.on('listening', this._server.emit.bind(this._server, 'listening'));
this._httpServer.on('upgrade', (req, socket, head) => { this._httpServer.on('upgrade', (req, socket, head) => {
this._logger.debug(`[HttpServer] Upgrade to WebSocket: ${req.method} ${req.url}`);
if (!req.url?.startsWith(path)) { if (!req.url?.startsWith(path)) {
this._logger.debug(`Skipping upgrade of http request due to incorrect path [${req.url}]`); this._logger.debug(`Skipping upgrade of http request due to incorrect path [${req.url}]`);