bxo 0.0.7 โ 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/websocket-example.ts +140 -26
- package/package.json +1 -1
- package/src/index.ts +63 -13
- package/test-enhanced-websocket.js +68 -0
|
@@ -9,19 +9,28 @@ async function main() {
|
|
|
9
9
|
<!DOCTYPE html>
|
|
10
10
|
<html>
|
|
11
11
|
<head>
|
|
12
|
-
<title>BXO WebSocket Example</title>
|
|
12
|
+
<title>BXO WebSocket Example with Client ID & Cookies</title>
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
|
-
<h1>BXO WebSocket Example</h1>
|
|
15
|
+
<h1>BXO WebSocket Example with Client ID, Cookies, Search Params & Auth</h1>
|
|
16
16
|
<div id="messages"></div>
|
|
17
17
|
<input type="text" id="messageInput" placeholder="Type a message...">
|
|
18
18
|
<button onclick="sendMessage()">Send</button>
|
|
19
19
|
<button onclick="connect()">Connect</button>
|
|
20
|
+
<button onclick="connectWithParams()">Connect with Search Params</button>
|
|
21
|
+
<button onclick="connectWithAuth()">Connect with Auth</button>
|
|
20
22
|
<button onclick="disconnect()">Disconnect</button>
|
|
23
|
+
<button onclick="setCookie()">Set Test Cookie</button>
|
|
21
24
|
|
|
22
25
|
<script>
|
|
23
26
|
let ws = null;
|
|
24
27
|
|
|
28
|
+
function setCookie() {
|
|
29
|
+
document.cookie = "testCookie=hello_from_client; path=/";
|
|
30
|
+
document.cookie = "sessionId=abc123; path=/";
|
|
31
|
+
addMessage('Cookies set! Refresh and reconnect to see them in server logs.');
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
function connect() {
|
|
26
35
|
ws = new WebSocket('ws://localhost:3000/ws');
|
|
27
36
|
|
|
@@ -42,6 +51,48 @@ async function main() {
|
|
|
42
51
|
};
|
|
43
52
|
}
|
|
44
53
|
|
|
54
|
+
function connectWithParams() {
|
|
55
|
+
ws = new WebSocket('ws://localhost:3000/ws?room=test&user=john&theme=dark');
|
|
56
|
+
|
|
57
|
+
ws.onopen = function() {
|
|
58
|
+
addMessage('Connected to WebSocket with search params');
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
ws.onmessage = function(event) {
|
|
62
|
+
addMessage('Received: ' + event.data);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
ws.onclose = function() {
|
|
66
|
+
addMessage('Disconnected from WebSocket');
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
ws.onerror = function(error) {
|
|
70
|
+
addMessage('Error: ' + error);
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function connectWithAuth() {
|
|
75
|
+
// Note: Browser WebSocket API doesn't support custom headers directly
|
|
76
|
+
// This would typically be done server-side or with a library
|
|
77
|
+
ws = new WebSocket('ws://localhost:3000/ws?token=abc123&auth=Bearer%20token123');
|
|
78
|
+
|
|
79
|
+
ws.onopen = function() {
|
|
80
|
+
addMessage('Connected to WebSocket with auth params');
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
ws.onmessage = function(event) {
|
|
84
|
+
addMessage('Received: ' + event.data);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
ws.onclose = function() {
|
|
88
|
+
addMessage('Disconnected from WebSocket');
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
ws.onerror = function(error) {
|
|
92
|
+
addMessage('Error: ' + error);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
45
96
|
function disconnect() {
|
|
46
97
|
if (ws) {
|
|
47
98
|
ws.close();
|
|
@@ -73,60 +124,123 @@ async function main() {
|
|
|
73
124
|
}
|
|
74
125
|
});
|
|
75
126
|
</script>
|
|
76
|
-
`, 200
|
|
77
|
-
"Content-Type": "text/html"
|
|
78
|
-
});
|
|
127
|
+
`, 200);
|
|
79
128
|
});
|
|
80
129
|
|
|
81
|
-
// WebSocket route
|
|
130
|
+
// WebSocket route with enhanced client identification
|
|
82
131
|
app.ws("/ws", {
|
|
83
132
|
open(ws) {
|
|
84
|
-
|
|
85
|
-
|
|
133
|
+
const clientInfo = ws.data;
|
|
134
|
+
console.log("๐ WebSocket connection opened:");
|
|
135
|
+
console.log(` ๐ Client ID: ${clientInfo.id}`);
|
|
136
|
+
console.log(` ๐ Connection ID: ${clientInfo.connectionId}`);
|
|
137
|
+
console.log(` ๐ Client IP: ${clientInfo.ip}`);
|
|
138
|
+
console.log(` ๐ฅ๏ธ User Agent: ${clientInfo.userAgent}`);
|
|
139
|
+
console.log(` ๐ฏ Origin: ${clientInfo.origin}`);
|
|
140
|
+
console.log(` ๐ Host: ${clientInfo.host}`);
|
|
141
|
+
console.log(` ๐ Path: ${clientInfo.path}`);
|
|
142
|
+
console.log(` ๐ช Cookies:`, clientInfo.cookies);
|
|
143
|
+
console.log(` ๐ Search Params:`, clientInfo.searchParams);
|
|
144
|
+
console.log(` ๐ Authorization:`, clientInfo.authorization || 'None');
|
|
145
|
+
|
|
146
|
+
// Check for authentication
|
|
147
|
+
if (clientInfo.authorization) {
|
|
148
|
+
console.log(` โ
Authenticated user detected`);
|
|
149
|
+
ws.send(`Welcome authenticated user! Your WebSocket ID is: ${clientInfo.id}`);
|
|
150
|
+
} else if (clientInfo.searchParams.token || clientInfo.searchParams.auth) {
|
|
151
|
+
console.log(` ๐ Token-based auth detected`);
|
|
152
|
+
ws.send(`Welcome! Token detected. Your WebSocket ID is: ${clientInfo.id}`);
|
|
153
|
+
} else {
|
|
154
|
+
ws.send(`Welcome! Your WebSocket ID is: ${clientInfo.id}`);
|
|
155
|
+
}
|
|
86
156
|
},
|
|
87
157
|
|
|
88
158
|
message(ws, message) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
159
|
+
const clientInfo = ws.data;
|
|
160
|
+
console.log(`๐ฌ Message from ${clientInfo.id} (${clientInfo.ip}):`, message);
|
|
161
|
+
console.log(` ๐ช Client cookies:`, clientInfo.cookies);
|
|
162
|
+
console.log(` ๐ Search params:`, clientInfo.searchParams);
|
|
163
|
+
console.log(` ๐ Auth:`, clientInfo.authorization || 'None');
|
|
164
|
+
|
|
165
|
+
// Echo the message back with client ID and context
|
|
166
|
+
let response = `[${clientInfo.id}] Echo: ${message}`;
|
|
167
|
+
|
|
168
|
+
// Add context based on search params
|
|
169
|
+
if (clientInfo.searchParams.room) {
|
|
170
|
+
response += ` (Room: ${clientInfo.searchParams.room})`;
|
|
171
|
+
}
|
|
172
|
+
if (clientInfo.searchParams.user) {
|
|
173
|
+
response += ` (User: ${clientInfo.searchParams.user})`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
ws.send(response);
|
|
92
177
|
},
|
|
93
178
|
|
|
94
179
|
close(ws, code, reason) {
|
|
95
|
-
|
|
180
|
+
const clientInfo = ws.data;
|
|
181
|
+
console.log(`โ WebSocket connection closed for ${clientInfo.id}: ${code} ${reason}`);
|
|
96
182
|
},
|
|
97
183
|
|
|
98
184
|
ping(ws, data) {
|
|
99
|
-
|
|
185
|
+
const clientInfo = ws.data;
|
|
186
|
+
console.log(`๐ Ping received from ${clientInfo.id}:`, data);
|
|
100
187
|
},
|
|
101
188
|
|
|
102
189
|
pong(ws, data) {
|
|
103
|
-
|
|
190
|
+
const clientInfo = ws.data;
|
|
191
|
+
console.log(`๐ Pong received from ${clientInfo.id}:`, data);
|
|
104
192
|
}
|
|
105
193
|
});
|
|
106
194
|
|
|
107
|
-
//
|
|
195
|
+
// Chat room WebSocket with client identification
|
|
108
196
|
app.ws("/chat/:room", {
|
|
109
197
|
open(ws) {
|
|
110
|
-
|
|
111
|
-
|
|
198
|
+
const clientInfo = ws.data;
|
|
199
|
+
const room = clientInfo.path.split('/').pop() || 'unknown';
|
|
200
|
+
console.log(`๐ Chat room connection opened for room: ${room}`);
|
|
201
|
+
console.log(` ๐ Client: ${clientInfo.id} (${clientInfo.ip})`);
|
|
202
|
+
console.log(` ๐ช Cookies:`, clientInfo.cookies);
|
|
203
|
+
console.log(` ๐ Search Params:`, clientInfo.searchParams);
|
|
204
|
+
console.log(` ๐ Authorization:`, clientInfo.authorization || 'None');
|
|
205
|
+
|
|
206
|
+
// Check for user info in search params
|
|
207
|
+
const username = clientInfo.searchParams.user || clientInfo.searchParams.username || 'Anonymous';
|
|
208
|
+
ws.send(`Welcome to chat room: ${room}! Your ID is: ${clientInfo.id}, Username: ${username}`);
|
|
112
209
|
},
|
|
113
210
|
|
|
114
211
|
message(ws, message) {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
212
|
+
const clientInfo = ws.data;
|
|
213
|
+
const room = clientInfo.path.split('/').pop() || 'unknown';
|
|
214
|
+
const username = clientInfo.searchParams.user || clientInfo.searchParams.username || 'Anonymous';
|
|
215
|
+
console.log(`๐ฌ Message in room ${room} from ${clientInfo.id} (${username}):`, message);
|
|
216
|
+
console.log(` ๐ช Client cookies:`, clientInfo.cookies);
|
|
217
|
+
console.log(` ๐ Search params:`, clientInfo.searchParams);
|
|
218
|
+
ws.send(`[${room}] [${username}] [${clientInfo.id}] Echo: ${message}`);
|
|
118
219
|
},
|
|
119
220
|
|
|
120
221
|
close(ws, code, reason) {
|
|
121
|
-
const
|
|
122
|
-
|
|
222
|
+
const clientInfo = ws.data;
|
|
223
|
+
const room = clientInfo.path.split('/').pop() || 'unknown';
|
|
224
|
+
console.log(`โ Chat room connection closed for room ${room} (${clientInfo.id}): ${code} ${reason}`);
|
|
123
225
|
}
|
|
124
226
|
});
|
|
125
227
|
|
|
126
228
|
app.start();
|
|
127
|
-
console.log(
|
|
128
|
-
console.log(
|
|
129
|
-
console.log(
|
|
229
|
+
console.log(`๐ Server is running on http://localhost:${app.server?.port}`);
|
|
230
|
+
console.log(`๐ WebSocket available at ws://localhost:${app.server?.port}/ws`);
|
|
231
|
+
console.log(`๐ฌ Chat WebSocket available at ws://localhost:${app.server?.port}/chat/:room`);
|
|
232
|
+
console.log(`\n๐ Features demonstrated:`);
|
|
233
|
+
console.log(` โข ws.id - Short, unique client identifier`);
|
|
234
|
+
console.log(` โข ws.data.connectionId - Detailed connection ID`);
|
|
235
|
+
console.log(` โข ws.data.cookies - Parsed cookies from handshake`);
|
|
236
|
+
console.log(` โข ws.data.searchParams - Query parameters from URL`);
|
|
237
|
+
console.log(` โข ws.data.authorization - Authorization header`);
|
|
238
|
+
console.log(` โข Client IP, User Agent, Origin tracking`);
|
|
239
|
+
console.log(`\n๐งช Test URLs:`);
|
|
240
|
+
console.log(` โข Basic: ws://localhost:${app.server?.port}/ws`);
|
|
241
|
+
console.log(` โข With params: ws://localhost:${app.server?.port}/ws?room=test&user=john&theme=dark`);
|
|
242
|
+
console.log(` โข With auth: ws://localhost:${app.server?.port}/ws?token=abc123&auth=Bearer%20token123`);
|
|
243
|
+
console.log(` โข Chat room: ws://localhost:${app.server?.port}/chat/general?user=alice&theme=light`);
|
|
130
244
|
}
|
|
131
245
|
|
|
132
|
-
main().catch(console.error);
|
|
246
|
+
main().catch(console.error);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -92,6 +92,20 @@ type Handler<P extends string, S extends RouteSchema | undefined = undefined> =
|
|
|
92
92
|
app: BXO
|
|
93
93
|
) => Response | string | BunFile | Promise<Response | string | BunFile>
|
|
94
94
|
|
|
95
|
+
// WebSocket client information type
|
|
96
|
+
export type WebSocketClientInfo = {
|
|
97
|
+
id: string; // Short, unique identifier for the WebSocket connection
|
|
98
|
+
path: string;
|
|
99
|
+
ip: string;
|
|
100
|
+
userAgent: string;
|
|
101
|
+
origin: string;
|
|
102
|
+
host: string;
|
|
103
|
+
connectionId: string; // Longer, more detailed connection identifier
|
|
104
|
+
cookies: Record<string, string>; // Parsed cookies from the handshake
|
|
105
|
+
searchParams: Record<string, string | string[]>; // Query parameters from the URL
|
|
106
|
+
authorization?: string; // Authorization header (Bearer token, Basic auth, etc.)
|
|
107
|
+
};
|
|
108
|
+
|
|
95
109
|
// WebSocket handler types
|
|
96
110
|
export type WebSocketHandler<T = any> = {
|
|
97
111
|
message?(ws: Bun.ServerWebSocket<T>, message: string | Buffer): void | Promise<void>;
|
|
@@ -436,22 +450,22 @@ export default class BXO {
|
|
|
436
450
|
|
|
437
451
|
// Create WebSocket configuration if we have WebSocket routes
|
|
438
452
|
const websocketConfig = hasWebSocketRoutes ? {
|
|
439
|
-
message: (ws: Bun.ServerWebSocket<
|
|
453
|
+
message: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, message: string | Buffer) => {
|
|
440
454
|
this.handleWebSocketMessage(ws, message);
|
|
441
455
|
},
|
|
442
|
-
open: (ws: Bun.ServerWebSocket<
|
|
456
|
+
open: (ws: Bun.ServerWebSocket<WebSocketClientInfo>) => {
|
|
443
457
|
this.handleWebSocketOpen(ws);
|
|
444
458
|
},
|
|
445
|
-
close: (ws: Bun.ServerWebSocket<
|
|
459
|
+
close: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, code: number, reason: string) => {
|
|
446
460
|
this.handleWebSocketClose(ws, code, reason);
|
|
447
461
|
},
|
|
448
|
-
drain: (ws: Bun.ServerWebSocket<
|
|
462
|
+
drain: (ws: Bun.ServerWebSocket<WebSocketClientInfo>) => {
|
|
449
463
|
this.handleWebSocketDrain(ws);
|
|
450
464
|
},
|
|
451
|
-
ping: (ws: Bun.ServerWebSocket<
|
|
465
|
+
ping: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer) => {
|
|
452
466
|
this.handleWebSocketPing(ws, data);
|
|
453
467
|
},
|
|
454
|
-
pong: (ws: Bun.ServerWebSocket<
|
|
468
|
+
pong: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer) => {
|
|
455
469
|
this.handleWebSocketPong(ws, data);
|
|
456
470
|
}
|
|
457
471
|
} : undefined;
|
|
@@ -467,8 +481,44 @@ export default class BXO {
|
|
|
467
481
|
const url = new URL(req.url);
|
|
468
482
|
const wsRoute = this.findWebSocketRoute(url.pathname);
|
|
469
483
|
if (wsRoute) {
|
|
484
|
+
// Capture client information during handshake
|
|
485
|
+
const shortId = Math.random().toString(36).substr(2, 8);
|
|
486
|
+
const connectionId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
487
|
+
const cookieHeader = req.headers.get("cookie");
|
|
488
|
+
const authHeader = req.headers.get("authorization");
|
|
489
|
+
|
|
490
|
+
// Parse search parameters from URL
|
|
491
|
+
const searchParams: Record<string, string | string[]> = {};
|
|
492
|
+
for (const [key, value] of url.searchParams.entries()) {
|
|
493
|
+
if (key in searchParams) {
|
|
494
|
+
const existing = searchParams[key];
|
|
495
|
+
if (Array.isArray(existing)) {
|
|
496
|
+
existing.push(value);
|
|
497
|
+
} else {
|
|
498
|
+
searchParams[key] = [existing as string, value];
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
searchParams[key] = value;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const clientInfo = {
|
|
506
|
+
id: shortId, // Short, easy-to-use ID
|
|
507
|
+
path: url.pathname,
|
|
508
|
+
ip: req.headers.get("x-forwarded-for") ||
|
|
509
|
+
req.headers.get("x-real-ip") ||
|
|
510
|
+
"unknown",
|
|
511
|
+
userAgent: req.headers.get("user-agent") || "unknown",
|
|
512
|
+
origin: req.headers.get("origin") || "unknown",
|
|
513
|
+
host: req.headers.get("host") || "unknown",
|
|
514
|
+
connectionId: connectionId, // Longer, more detailed ID
|
|
515
|
+
cookies: cookieHeader ? parseCookies(cookieHeader) : {},
|
|
516
|
+
searchParams: searchParams, // Query parameters from URL
|
|
517
|
+
authorization: authHeader || undefined // Authorization header
|
|
518
|
+
};
|
|
519
|
+
|
|
470
520
|
const success = server.upgrade(req, {
|
|
471
|
-
data:
|
|
521
|
+
data: clientInfo
|
|
472
522
|
});
|
|
473
523
|
if (success) {
|
|
474
524
|
return; // WebSocket upgrade successful
|
|
@@ -533,7 +583,7 @@ export default class BXO {
|
|
|
533
583
|
return null;
|
|
534
584
|
}
|
|
535
585
|
|
|
536
|
-
private handleWebSocketMessage(ws: Bun.ServerWebSocket<
|
|
586
|
+
private handleWebSocketMessage(ws: Bun.ServerWebSocket<WebSocketClientInfo>, message: string | Buffer): void {
|
|
537
587
|
const route = this.findWebSocketRoute(ws.data?.path || "");
|
|
538
588
|
if (route?.websocketHandler?.message) {
|
|
539
589
|
try {
|
|
@@ -544,7 +594,7 @@ export default class BXO {
|
|
|
544
594
|
}
|
|
545
595
|
}
|
|
546
596
|
|
|
547
|
-
private handleWebSocketOpen(ws: Bun.ServerWebSocket<
|
|
597
|
+
private handleWebSocketOpen(ws: Bun.ServerWebSocket<WebSocketClientInfo>): void {
|
|
548
598
|
const route = this.findWebSocketRoute(ws.data?.path || "");
|
|
549
599
|
if (route?.websocketHandler?.open) {
|
|
550
600
|
try {
|
|
@@ -555,7 +605,7 @@ export default class BXO {
|
|
|
555
605
|
}
|
|
556
606
|
}
|
|
557
607
|
|
|
558
|
-
private handleWebSocketClose(ws: Bun.ServerWebSocket<
|
|
608
|
+
private handleWebSocketClose(ws: Bun.ServerWebSocket<WebSocketClientInfo>, code: number, reason: string): void {
|
|
559
609
|
const route = this.findWebSocketRoute(ws.data?.path || "");
|
|
560
610
|
if (route?.websocketHandler?.close) {
|
|
561
611
|
try {
|
|
@@ -566,7 +616,7 @@ export default class BXO {
|
|
|
566
616
|
}
|
|
567
617
|
}
|
|
568
618
|
|
|
569
|
-
private handleWebSocketDrain(ws: Bun.ServerWebSocket<
|
|
619
|
+
private handleWebSocketDrain(ws: Bun.ServerWebSocket<WebSocketClientInfo>): void {
|
|
570
620
|
const route = this.findWebSocketRoute(ws.data?.path || "");
|
|
571
621
|
if (route?.websocketHandler?.drain) {
|
|
572
622
|
try {
|
|
@@ -577,7 +627,7 @@ export default class BXO {
|
|
|
577
627
|
}
|
|
578
628
|
}
|
|
579
629
|
|
|
580
|
-
private handleWebSocketPing(ws: Bun.ServerWebSocket<
|
|
630
|
+
private handleWebSocketPing(ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer): void {
|
|
581
631
|
const route = this.findWebSocketRoute(ws.data?.path || "");
|
|
582
632
|
if (route?.websocketHandler?.ping) {
|
|
583
633
|
try {
|
|
@@ -588,7 +638,7 @@ export default class BXO {
|
|
|
588
638
|
}
|
|
589
639
|
}
|
|
590
640
|
|
|
591
|
-
private handleWebSocketPong(ws: Bun.ServerWebSocket<
|
|
641
|
+
private handleWebSocketPong(ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer): void {
|
|
592
642
|
const route = this.findWebSocketRoute(ws.data?.path || "");
|
|
593
643
|
if (route?.websocketHandler?.pong) {
|
|
594
644
|
try {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Comprehensive test for enhanced WebSocket client identification
|
|
2
|
+
console.log('๐งช Testing Enhanced WebSocket Client Identification...\n');
|
|
3
|
+
|
|
4
|
+
// Test 1: Basic WebSocket connection
|
|
5
|
+
console.log('1. Testing basic WebSocket connection');
|
|
6
|
+
const ws1 = new WebSocket('ws://localhost:3000/ws');
|
|
7
|
+
|
|
8
|
+
ws1.onopen = function() {
|
|
9
|
+
console.log('โ Connected to basic WebSocket');
|
|
10
|
+
ws1.send('Hello from basic connection!');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
ws1.onmessage = function(event) {
|
|
14
|
+
console.log('โ Received:', event.data);
|
|
15
|
+
ws1.close();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
ws1.onclose = function() {
|
|
19
|
+
console.log('โ Basic connection closed\n');
|
|
20
|
+
|
|
21
|
+
// Test 2: WebSocket with search parameters
|
|
22
|
+
console.log('2. Testing WebSocket with search parameters');
|
|
23
|
+
const ws2 = new WebSocket('ws://localhost:3000/ws?room=test&user=john&theme=dark&token=abc123');
|
|
24
|
+
|
|
25
|
+
ws2.onopen = function() {
|
|
26
|
+
console.log('โ Connected with search params');
|
|
27
|
+
ws2.send('Hello from connection with params!');
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
ws2.onmessage = function(event) {
|
|
31
|
+
console.log('โ Received:', event.data);
|
|
32
|
+
ws2.close();
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
ws2.onclose = function() {
|
|
36
|
+
console.log('โ Search params connection closed\n');
|
|
37
|
+
|
|
38
|
+
// Test 3: Chat room with search parameters
|
|
39
|
+
console.log('3. Testing chat room with search parameters');
|
|
40
|
+
const ws3 = new WebSocket('ws://localhost:3000/chat/general?user=alice&theme=light&role=moderator');
|
|
41
|
+
|
|
42
|
+
ws3.onopen = function() {
|
|
43
|
+
console.log('โ Connected to chat room with params');
|
|
44
|
+
ws3.send('Hello from chat room!');
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
ws3.onmessage = function(event) {
|
|
48
|
+
console.log('โ Received:', event.data);
|
|
49
|
+
ws3.close();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
ws3.onclose = function() {
|
|
53
|
+
console.log('โ Chat room connection closed');
|
|
54
|
+
console.log('\nโ
All tests completed! Check the server logs to see:');
|
|
55
|
+
console.log(' โข ws.id - Short client identifier');
|
|
56
|
+
console.log(' โข ws.data.searchParams - Query parameters');
|
|
57
|
+
console.log(' โข ws.data.cookies - Parsed cookies');
|
|
58
|
+
console.log(' โข ws.data.authorization - Auth header');
|
|
59
|
+
console.log(' โข Client IP and other identification info');
|
|
60
|
+
process.exit(0);
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
ws1.onerror = function(error) {
|
|
66
|
+
console.error('โ WebSocket error:', error);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
};
|