@@ -8,6 +8,77 @@ import type { Request, Response } from "../protocol.js";
8
8
import type { ResilientWebSocketConfig } from "./resilient-websocket.js" ;
9
9
import { ResilientWebSocket } from "./resilient-websocket.js" ;
10
10
11
+ /**
12
+ * Detects if the code is running in a regular DOM or Web Worker context.
13
+ * @returns true if running in a DOM or Web Worker context, false if running in Node.js
14
+ */
15
+ function isBrowser ( ) : boolean {
16
+ try {
17
+ // Check for browser's window object (DOM context)
18
+ if ( typeof globalThis !== "undefined" ) {
19
+ const global = globalThis as any ;
20
+ if ( global . window && global . window . document ) {
21
+ return true ;
22
+ }
23
+
24
+ // Check for Web Worker context (has importScripts but no window)
25
+ if ( typeof global . importScripts === "function" && ! global . window ) {
26
+ return true ;
27
+ }
28
+ }
29
+
30
+ // Node.js environment
31
+ return false ;
32
+ } catch {
33
+ // If any error occurs, assume Node.js environment
34
+ return false ;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Adds authentication to either the URL as a query parameter or as an Authorization header.
40
+ *
41
+ * Browsers don't support custom headers for WebSocket connections, so if a browser is detected,
42
+ * the token is added as a query parameter instead. Else, the token is added as an Authorization header.
43
+ *
44
+ * @param url - The WebSocket URL
45
+ * @param token - The authentication token
46
+ * @param wsOptions - Existing WebSocket options
47
+ * @returns Object containing the modified endpoint and wsOptions
48
+ */
49
+ function addAuthentication (
50
+ url : string ,
51
+ token : string ,
52
+ wsOptions : any = { }
53
+ ) : { endpoint : string ; wsOptions : any } {
54
+ if ( isBrowser ( ) ) {
55
+ // Browser: Add token as query parameter
56
+ const urlObj = new URL ( url ) ;
57
+ urlObj . searchParams . set ( "ACCESS_TOKEN" , token ) ;
58
+
59
+ // For browsers, we need to filter out any options that aren't valid for WebSocket constructor
60
+ // Browser WebSocket constructor only accepts protocols as second parameter
61
+ const browserWsOptions = wsOptions . protocols ? wsOptions . protocols : undefined ;
62
+
63
+ return {
64
+ endpoint : urlObj . toString ( ) ,
65
+ wsOptions : browserWsOptions ,
66
+ } ;
67
+ } else {
68
+ // Node.js: Add Authorization header
69
+ return {
70
+ endpoint : url ,
71
+ wsOptions : {
72
+ ...wsOptions ,
73
+ headers : {
74
+ ...wsOptions . headers ,
75
+ Authorization : `Bearer ${ token } ` ,
76
+ } ,
77
+ } ,
78
+ } ;
79
+ }
80
+ }
81
+
11
82
const DEFAULT_NUM_CONNECTIONS = 4 ;
12
83
13
84
export type WebSocketPoolConfig = {
@@ -63,15 +134,17 @@ export class WebSocketPool {
63
134
if ( ! url ) {
64
135
throw new Error ( `URLs must not be null or empty` ) ;
65
136
}
66
- const wsOptions = {
67
- ...config . rwsConfig ?. wsOptions ,
68
- headers : {
69
- Authorization : `Bearer ${ config . token } ` ,
70
- } ,
71
- } ;
137
+
138
+ // Apply authentication based on environment (browser vs Node.js)
139
+ const { endpoint, wsOptions } = addAuthentication (
140
+ url ,
141
+ config . token ,
142
+ config . rwsConfig ?. wsOptions
143
+ ) ;
144
+
72
145
const rws = new ResilientWebSocket ( {
73
146
...config . rwsConfig ,
74
- endpoint : url ,
147
+ endpoint,
75
148
wsOptions,
76
149
logger,
77
150
} ) ;
0 commit comments