basic chat

This commit is contained in:
2025-09-28 14:55:09 -04:00
parent 9306632cc1
commit 0cc0ce13e7
12 changed files with 347 additions and 25 deletions

View File

@@ -1,9 +1,10 @@
import path from 'node:path';
import {IncomingMessage} from 'node:http';
import {LoggerFactory} from '@techniker-me/logger';
import HttpServer from './net/http/HttpServer';
import HealthCheckRoute from './health/HealthCheckRoute';
import HealthCheck from './health/HealthCheck';
import WebSocketServer from './net/websocket/WebSocketServer';
import WebSocketServer, {ExtendedWebSocket} from './net/websocket/WebSocketServer';
const logger = LoggerFactory.getLogger('Server');
const healthCheck = new HealthCheck();
@@ -12,12 +13,45 @@ const healthCheckRoute = new HealthCheckRoute(healthCheck);
const httpServer = new HttpServer('http', 3000, healthCheckRoute, {}, '', [], path.resolve(process.cwd(), 'assets', 'favicon', 'favicon.ico'), {});
httpServer.on('error', () => logger.error('[HttpServer] Error'));
const sockets = new Map<string, ExtendedWebSocket>();
function connectDelegate(connection: ExtendedWebSocket, req: IncomingMessage) {
console.log('[Server] Connect delegate');
sockets.set(connection.id, connection);
}
function requestDelegate(connection: ExtendedWebSocket, message: Buffer) {
console.log('[Server] Request delegate');
try {
const messageJson = JSON.parse(message.toString());
console.log('messageJson', messageJson);
if (messageJson.ping) {
const serverTime = Date.now();
const rtt = serverTime - messageJson.ping.sentAt;
connection.send(
JSON.stringify({
pong: {
sentAt: serverTime,
rtt: rtt
},
...messageJson
})
);
}
else if (messageJson.message) {
sockets.forEach(socket => {
socket.send(JSON.stringify({...messageJson}));
});
}
} catch (error) {
console.log('error requestingDelegate to handle websocket message', error);
}
}
function disconnectDelegate(connection: ExtendedWebSocket, reasonCode: number, description: string) {
@@ -29,18 +63,16 @@ function pongDelegate(connection: ExtendedWebSocket, message: Buffer) {
}
httpServer
.start()
.then(() => {
const server = httpServer.getServer();
.start()
.then(() => {
const server = httpServer.getServer();
if (server) {
const websocketServer = new WebSocketServer(server, {path: '/ws'});
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));
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

@@ -8,7 +8,7 @@ import type {ILogger} from '@techniker-me/logger';
import {LoggerFactory} from '@techniker-me/logger';
import IRoutes from './IRoutes';
import {Subject} from '@techniker-me/tools';
import express, { RequestHandler } from 'express';
import express, {RequestHandler} from 'express';
import morgan from 'morgan';
import favicon from 'serve-favicon';
import bodyParser from 'body-parser';
@@ -155,7 +155,6 @@ export default class HttpServer {
this._eventEmitter.on(event, handler);
}
public getServer(): Nullable<Server> {
return this._server.value;
}
@@ -351,10 +350,9 @@ export default class HttpServer {
const registerRoutes = (method: string, routes: Record<string, RequestHandler>): void => {
for (const route of Object.entries(routes)) {
if (!route) {
continue;
}
if (!route) {
continue;
}
const [name, handler] = route;
@@ -370,7 +368,7 @@ export default class HttpServer {
this._logger.debug(`Registering [${method}] route [${name}] handler`);
app[method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete'](name, handler);
}
}
};
registerRoutes('GET', this._routes.getGETRoutes());
registerRoutes('POST', this._routes.getPOSTRoutes());

View File

@@ -6,7 +6,7 @@ import Assert from '../../lang/Assert';
import Strings from '../../lang/Strings';
import WebsocketExtensions from 'websocket-extensions';
interface ExtendedWebSocket extends WebSocket {
export interface ExtendedWebSocket extends WebSocket {
id: string;
remoteAddress: string;
isOpen(): boolean;
@@ -124,7 +124,7 @@ export default class WebSocketServer {
let closed = false;
try {
const extendedConnection = connection as ExtendedWebSocket;
const extendedConnection = connection as ExtendedWebSocket;
extendedConnection.id = Strings.randomString(connectionIdLength);
extendedConnection.remoteAddress = getRemoteAddress(extendedConnection, req);
extendedConnection.isOpen = () => connection.readyState === ws.OPEN;