@@ -31,7 +31,7 @@ const EVENT_CLIENT_CONTEXT_CLOSED = "EVENT_CLIENT_CONTEXT_CLOSED";
31
31
32
32
/** TODO(gpl) Refine this list */
33
33
export type WebsocketClientType = "browser" | "go-client" | "vs-code" ;
34
- export namespace WebsocketClientType {
34
+ namespace WebsocketClientType {
35
35
export function getClientType ( req : express . Request ) : WebsocketClientType | undefined {
36
36
const userAgent = req . headers [ "user-agent" ] ;
37
37
@@ -58,9 +58,10 @@ export interface ClientMetadata {
58
58
authLevel : WebsocketAuthenticationLevel ,
59
59
sessionId ?: string ;
60
60
userId ?: string ;
61
+ type ?: WebsocketClientType ;
61
62
}
62
63
export namespace ClientMetadata {
63
- export function from ( userId : string | undefined , sessionId ?: string ) : ClientMetadata {
64
+ export function from ( userId : string | undefined , sessionId ?: string , type ?: WebsocketClientType ) : ClientMetadata {
64
65
let id = "anonymous" ;
65
66
let authLevel : WebsocketAuthenticationLevel = "anonymous" ;
66
67
if ( userId ) {
@@ -70,25 +71,22 @@ export namespace ClientMetadata {
70
71
id = `session-${ sessionId } ` ;
71
72
authLevel = "session" ;
72
73
}
73
- return { id, authLevel, userId, sessionId } ;
74
+ return { id, authLevel, userId, sessionId, type } ;
74
75
}
75
76
}
76
77
77
78
export class WebsocketClientContext {
78
79
constructor (
79
- /**
80
- * We try to be as specific as we can when identifying client connections.
81
- * If we now the userId, this will be the userId. If we just have a session, this is the sessionId (prefixed by `session-`).
82
- * If it's a
83
- */
84
- public readonly clientId : string ,
85
-
86
- public readonly authLevel : WebsocketAuthenticationLevel
80
+ public readonly clientMetadata : ClientMetadata ,
87
81
) { }
88
82
89
83
/** This list of endpoints serving client connections 1-1 */
90
84
protected servers : GitpodServerImpl [ ] = [ ] ;
91
85
86
+ get clientId ( ) : string {
87
+ return this . clientMetadata . id ;
88
+ }
89
+
92
90
addEndpoint ( server : GitpodServerImpl ) {
93
91
this . servers . push ( server ) ;
94
92
}
@@ -124,7 +122,7 @@ export class WebsocketConnectionManager implements ConnectionHandler {
124
122
this . createProxyTarget . bind ( this ) ,
125
123
this . createAccessGuard . bind ( this ) ,
126
124
this . createRateLimiter . bind ( this ) ,
127
- this . getClientId . bind ( this ) ,
125
+ this . getClientMetadata . bind ( this ) ,
128
126
) ;
129
127
}
130
128
@@ -167,7 +165,7 @@ export class WebsocketConnectionManager implements ConnectionHandler {
167
165
clientRegion : takeFirst ( expressReq . headers [ "x-glb-client-region" ] ) ,
168
166
} ;
169
167
170
- gitpodServer . initialize ( client , user , resourceGuard , clientHeaderFields ) ;
168
+ gitpodServer . initialize ( client , user , resourceGuard , clientContext . clientMetadata , clientHeaderFields ) ;
171
169
client . onDidCloseConnection ( ( ) => {
172
170
gitpodServer . dispose ( ) ;
173
171
increaseApiConnectionClosedCounter ( ) ;
@@ -193,25 +191,26 @@ export class WebsocketConnectionManager implements ConnectionHandler {
193
191
}
194
192
195
193
protected getOrCreateClientContext ( expressReq : express . Request ) : WebsocketClientContext {
196
- const { id : clientId , authLevel } = this . getClientId ( expressReq ) ;
197
- let ctx = this . contexts . get ( clientId ) ;
194
+ const metadata = this . getClientMetadata ( expressReq ) ;
195
+ let ctx = this . contexts . get ( metadata . id ) ;
198
196
if ( ! ctx ) {
199
- ctx = new WebsocketClientContext ( clientId , authLevel ) ;
200
- this . contexts . set ( clientId , ctx ) ;
197
+ ctx = new WebsocketClientContext ( metadata ) ;
198
+ this . contexts . set ( metadata . id , ctx ) ;
201
199
this . events . emit ( EVENT_CLIENT_CONTEXT_CREATED , ctx ) ;
202
200
}
203
201
return ctx ;
204
202
}
205
203
206
- protected getClientId ( req ?: object ) : ClientMetadata {
204
+ protected getClientMetadata ( req ?: object ) : ClientMetadata {
207
205
const expressReq = req as express . Request ;
208
206
const user = expressReq . user ;
209
207
const sessionId = expressReq . session ?. id ;
210
- return ClientMetadata . from ( user ?. id , sessionId ) ;
208
+ const type = WebsocketClientType . getClientType ( expressReq ) ;
209
+ return ClientMetadata . from ( user ?. id , sessionId , type ) ;
211
210
}
212
211
213
212
protected createRateLimiter ( req ?: object ) : RateLimiter {
214
- const { id : clientId } = this . getClientId ( req ) ;
213
+ const { id : clientId } = this . getClientMetadata ( req ) ;
215
214
return {
216
215
user : clientId ,
217
216
consume : ( method ) => UserRateLimiter . instance ( this . rateLimiterConfig ) . consume ( clientId , method ) ,
@@ -294,12 +293,7 @@ class GitpodJsonRpcProxyFactory<T extends object> extends JsonRpcProxyFactory<T>
294
293
const userId = this . clientMetadata . userId ;
295
294
try {
296
295
// generic tracing data
297
- TraceContext . addNestedTags ( ctx , {
298
- client : {
299
- id : this . clientMetadata . id ,
300
- authLevel : this . clientMetadata . authLevel ,
301
- } ,
302
- } ) ;
296
+ traceClientMetadata ( ctx , this . clientMetadata ) ;
303
297
TraceContext . setOWI ( ctx , {
304
298
userId,
305
299
sessionId : this . clientMetadata . sessionId ,
@@ -353,4 +347,14 @@ class GitpodJsonRpcProxyFactory<T extends object> extends JsonRpcProxyFactory<T>
353
347
throw new ResponseError ( RPCErrorCodes . InvalidRequest , "notifications are not supported" ) ;
354
348
}
355
349
350
+ }
351
+
352
+ function traceClientMetadata ( ctx : TraceContext , clientMetadata : ClientMetadata ) {
353
+ TraceContext . addNestedTags ( ctx , {
354
+ client : {
355
+ id : clientMetadata . id ,
356
+ authLevel : clientMetadata . authLevel ,
357
+ type : clientMetadata . type ,
358
+ } ,
359
+ } ) ;
356
360
}
0 commit comments