import {Injectable, Inject} from '../../../di' import {HTTPKernelModule} from '../HTTPKernelModule' import {HTTPKernel} from '../HTTPKernel' import {Request} from '../../lifecycle/Request' import {Routing} from '../../../service/Routing' import {ActivatedRoute} from '../../routing/ActivatedRoute' import {Logging} from '../../../service/Logging' import {apiEvent, error} from '../../response/api' import {Bus, WebSocketBus} from '../../../support/bus' import {WebSocketCloseEvent} from '../../lifecycle/WebSocketCloseEvent' /** * HTTP kernel middleware that tries to find a registered route matching the request's * path and creates an ActivatedRoute instance from it, limited to websocket handling * routes. */ @Injectable() export class MountWebSocketRouteHTTPModule extends HTTPKernelModule { public readonly executeWithBlockingWriteback = true @Inject() protected readonly routing!: Routing @Inject() protected readonly logging!: Logging public static register(kernel: HTTPKernel): void { kernel.register(this).before() } public async apply(request: Request): Promise { const route = this.routing.match('ws', request.path) if ( route ) { this.logging.verbose(`Mounting activated WebSocket route: ${request.path} -> ${route}`) const activated = > request.make(ActivatedRoute, route, request.path) request.registerSingletonInstance>(ActivatedRoute, activated) } else { this.logging.debug(`No matching WebSocket route found for: ${request.method} -> ${request.path}`) // Send an error response on the socket to the client const ws = request.make(WebSocketBus) await ws.push(apiEvent(error('Endpoint is not a configured socket listener.'))) // Then, terminate the request & socket connections await request.make(Bus).push(new WebSocketCloseEvent()) request.response.blockingWriteback(true) } return request } }