@@ -15,7 +15,7 @@ import { log } from '@gitpod/gitpod-protocol/lib/util/logging';
15
15
import { increaseHttpRequestCounter } from '../prometheus-metrics' ;
16
16
17
17
export type HttpServer = http . Server | https . Server ;
18
- export type Route = string | RegExp ;
18
+ export type RouteMatcher = string | RegExp ;
19
19
export type MaybePromise = Promise < any > | any ;
20
20
21
21
export interface WsNextFunction {
@@ -31,10 +31,15 @@ export type WsHandler = WsRequestHandler | WsErrorHandler;
31
31
32
32
export type WsConnectionFilter = websocket . VerifyClientCallbackAsync | websocket . VerifyClientCallbackSync ;
33
33
34
+ interface Route {
35
+ matcher : RouteMatcher ;
36
+ handler : ( ws : websocket , req : express . Request ) => void ;
37
+ }
34
38
35
39
export class WsExpressHandler {
36
40
37
41
protected readonly wss : websocket . Server ;
42
+ protected readonly routes : Route [ ] = [ ] ;
38
43
39
44
constructor (
40
45
protected readonly httpServer : HttpServer ,
@@ -50,11 +55,12 @@ export class WsExpressHandler {
50
55
clientTracking : false ,
51
56
} ) ;
52
57
this . wss . on ( 'error' , ( err ) => {
53
- log . error ( 'Websocket error' , err , { ws : this . wss } ) ;
58
+ log . error ( 'websocket server error' , err , { wss : this . wss } ) ;
54
59
} ) ;
60
+ this . httpServer . on ( 'upgrade' , ( req : http . IncomingMessage , socket : net . Socket , head : Buffer ) => this . onUpgrade ( req , socket , head ) ) ;
55
61
}
56
62
57
- ws ( route : Route , handler : ( ws : websocket , request : express . Request ) => void , ...handlers : WsHandler [ ] ) : void {
63
+ ws ( matcher : RouteMatcher , handler : ( ws : websocket , request : express . Request ) => void , ...handlers : WsHandler [ ] ) : void {
58
64
const stack = WsLayer . createStack ( ...handlers ) ;
59
65
const dispatch = ( ws : websocket , request : express . Request ) => {
60
66
handler ( ws , request ) ;
@@ -68,24 +74,32 @@ export class WsExpressHandler {
68
74
} ) ;
69
75
}
70
76
71
- this . httpServer . on ( 'upgrade' , ( request : http . IncomingMessage , socket : net . Socket , head : Buffer ) => {
72
- const pathname = request . url ? url . parse ( request . url ) . pathname : undefined ;
73
- if ( this . matches ( route , pathname ) ) {
74
- this . wss . handleUpgrade ( request , socket , head , ws => {
75
- if ( ws . readyState === ws . OPEN ) {
76
- dispatch ( ws , request as express . Request ) ;
77
- } else {
78
- ws . on ( 'open' , ( ) => dispatch ( ws , request as express . Request ) ) ;
79
- }
80
- } ) ;
77
+ this . routes . push ( {
78
+ matcher,
79
+ handler : ( ws , req ) => {
80
+ if ( ws . readyState === ws . OPEN ) {
81
+ dispatch ( ws , req ) ;
82
+ } else {
83
+ ws . on ( 'open' , ( ) => dispatch ( ws , req ) ) ;
84
+ }
81
85
}
82
86
} ) ;
83
87
}
84
88
85
- protected matches ( route : Route , pathname : string | undefined | null ) : boolean {
86
- if ( route instanceof RegExp ) {
87
- return ! ! pathname && route . test ( pathname ) ;
89
+ protected onUpgrade ( request : http . IncomingMessage , socket : net . Socket , head : Buffer ) {
90
+ const pathname = request . url ? url . parse ( request . url ) . pathname : undefined ;
91
+ for ( const route of this . routes ) {
92
+ if ( this . matches ( route . matcher , pathname ) ) {
93
+ this . wss . handleUpgrade ( request , socket , head , ( ws ) => route . handler ( ws , request as express . Request ) ) ;
94
+ return ; // take the first match and stop
95
+ }
96
+ }
97
+ }
98
+
99
+ protected matches ( matcher : RouteMatcher , pathname : string | undefined | null ) : boolean {
100
+ if ( matcher instanceof RegExp ) {
101
+ return ! ! pathname && matcher . test ( pathname ) ;
88
102
}
89
- return pathname === route ;
103
+ return pathname === matcher ;
90
104
}
91
105
}
0 commit comments