11import { IncomingMessage } from 'http' ;
22import { Duplex } from 'stream' ;
33import { WebSocketServer } from 'ws' ;
4+ import { StatusError } from '@httptoolkit/util' ;
45
56import { wsEndpoints } from './endpoints/endpoint-index.js' ;
7+ import { resolveEndpointChain } from './endpoint-chain.js' ;
68
79const wss = new WebSocketServer ( { noServer : true } ) ;
810
@@ -19,36 +21,48 @@ export function handleWebSocketUpgrade(
1921 ? url . hostname . slice ( 0 , - options . rootDomain . length - 1 )
2022 : undefined ;
2123
22- const endpoint = wsEndpoints . find ( ep => ep . matchPath ( path , hostnamePrefix ) ) ;
23-
24- if ( ! endpoint ) {
25- console . log ( `WebSocket upgrade to ${ path } matched no endpoints` ) ;
26- socket . write ( 'HTTP/1.1 404 Not Found\r\n\r\n' ) ;
24+ let entries : typeof wsEndpoints extends Array < infer T > ? Array < { endpoint : T ; path : string } > : never ;
25+ try {
26+ entries = resolveEndpointChain ( wsEndpoints , path , hostnamePrefix ) ;
27+ } catch ( err ) {
28+ if ( err instanceof StatusError ) {
29+ console . log ( `WebSocket upgrade to ${ path } : ${ err . message } ` ) ;
30+ socket . write ( `HTTP/1.1 ${ err . statusCode } ${ err . statusCode === 404 ? 'Not Found' : 'Bad Request' } \r\n\r\n` ) ;
31+ } else {
32+ console . log ( `WebSocket upgrade to ${ path } : unexpected error` , err ) ;
33+ socket . write ( 'HTTP/1.1 500 Internal Server Error\r\n\r\n' ) ;
34+ }
2735 socket . destroy ( ) ;
2836 return ;
2937 }
3038
39+ const endpointNames = entries . map ( e => e . endpoint . name ) . join ( ' → ' ) ;
3140 console . log ( `WebSocket upgrade to ${ path } ${
3241 hostnamePrefix ? ` ('${ hostnamePrefix } ' prefix)` : ''
33- } matched: ${ endpoint . name } `) ;
42+ } matched: ${ endpointNames } `) ;
3443
3544 socket . on ( 'error' , ( err ) => {
3645 console . log ( 'WebSocket upgrade socket error:' , err . message ) ;
3746 } ) ;
3847
39- wss . handleUpgrade ( req , socket , head , ( ws ) => {
48+ wss . handleUpgrade ( req , socket , head , async ( ws ) => {
4049 ws . on ( 'error' , ( err ) => {
4150 console . log ( `WebSocket error on ${ path } :` , err . message ) ;
4251 } ) ;
4352
4453 try {
45- endpoint . handle ( ws , req , {
46- path,
47- query : url . searchParams
48- } ) ;
54+ for ( const { endpoint, path : entryPath } of entries ) {
55+ if ( ws . readyState !== ws . OPEN ) return ;
56+ await endpoint . handle ( ws , req , {
57+ path : entryPath ,
58+ query : url . searchParams
59+ } ) ;
60+ }
4961 } catch ( err ) {
5062 console . log ( `WebSocket handler error on ${ path } :` , err ) ;
51- ws . close ( 1011 , 'Internal error' ) ;
63+ if ( ws . readyState === ws . OPEN ) {
64+ ws . close ( 1011 , 'Internal error' ) ;
65+ }
5266 }
5367 } ) ;
5468}
0 commit comments