diff --git a/server/package.json b/server/package.json index 65bd1f36..2630c2f0 100644 --- a/server/package.json +++ b/server/package.json @@ -38,7 +38,6 @@ "@nestjs/mapped-types": "^2.0.2", "@nestjs/platform-fastify": "^10.2.7", "@nestjs/platform-socket.io": "^10.2.7", - "@nestjs/platform-ws": "^10.2.7", "@nestjs/typeorm": "^10.0.0", "@nestjs/websockets": "^10.2.7", "bcrypt": "^5.1.1", diff --git a/server/src/collaboration/adapter/collab-ws.adapter.ts b/server/src/collaboration/adapter/collab-ws.adapter.ts new file mode 100644 index 00000000..8a821ba9 --- /dev/null +++ b/server/src/collaboration/adapter/collab-ws.adapter.ts @@ -0,0 +1,39 @@ +import { WebSocketServer } from 'ws'; + +export class CollabWsAdapter { + private readonly wss: WebSocketServer; + + constructor() { + this.wss = new WebSocketServer({ noServer: true }); + } + + handleUpgrade(path: string, httpServer) { + httpServer.on('upgrade', (request, socket, head) => { + try { + const baseUrl = 'ws://' + request.headers.host + '/'; + const pathname = new URL(request.url, baseUrl).pathname; + + if (pathname === path) { + this.wss.handleUpgrade(request, socket, head, (ws) => { + this.wss.emit('connection', ws, request); + }); + } else if (pathname === '/socket.io/') { + return; + } else { + socket.destroy(); + } + } catch (err) { + socket.end('HTTP/1.1 400\r\n' + err.message); + } + }); + + return this.wss; + } + + public close() { + this.wss.clients.forEach((client) => { + client.terminate(); + }); + this.wss.close(); + } +} diff --git a/server/src/collaboration/collaboration.module.ts b/server/src/collaboration/collaboration.module.ts index 025eceff..3b607883 100644 --- a/server/src/collaboration/collaboration.module.ts +++ b/server/src/collaboration/collaboration.module.ts @@ -6,9 +6,9 @@ import { PersistenceExtension } from './extensions/persistence.extension'; import { PageModule } from '../core/page/page.module'; import { CollaborationGateway } from './collaboration.gateway'; import { HttpAdapterHost } from '@nestjs/core'; -import { WsAdapter } from '@nestjs/platform-ws'; -import WebSocket from 'ws'; +import { CollabWsAdapter } from './adapter/collab-ws.adapter'; import { IncomingMessage } from 'http'; +import { WebSocket } from 'ws'; @Module({ providers: [ @@ -19,29 +19,27 @@ import { IncomingMessage } from 'http'; imports: [UserModule, AuthModule, PageModule], }) export class CollaborationModule implements OnModuleInit, OnModuleDestroy { + private collabWsAdapter: CollabWsAdapter; + private path = '/collaboration'; + constructor( private readonly collaborationGateway: CollaborationGateway, private readonly httpAdapterHost: HttpAdapterHost, ) {} onModuleInit() { - const port = 0; // zero to reuse existing server port - const path = '/collaboration'; - + this.collabWsAdapter = new CollabWsAdapter(); const httpServer = this.httpAdapterHost.httpAdapter.getHttpServer(); - const wsAdapter = new WsAdapter(httpServer).create(port, { - path, - }); - wsAdapter.on( - 'connection', - (client: WebSocket, request: IncomingMessage) => { - this.collaborationGateway.handleConnection(client, request); - }, - ); + const wss = this.collabWsAdapter.handleUpgrade(this.path, httpServer); + + wss.on('connection', (client: WebSocket, request: IncomingMessage) => { + this.collaborationGateway.handleConnection(client, request); + }); } onModuleDestroy(): any { this.collaborationGateway.handleDestroy(); + this.collabWsAdapter.close(); } }