1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+ < head >
4+ < meta charset ="UTF-8 ">
5+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6+ < title > WebSocket Echo Test Client</ title >
7+ < style >
8+ body {
9+ font-family : Arial, sans-serif;
10+ max-width : 800px ;
11+ margin : 0 auto;
12+ padding : 20px ;
13+ }
14+ .container {
15+ border : 1px solid # ccc ;
16+ border-radius : 8px ;
17+ padding : 20px ;
18+ margin : 10px 0 ;
19+ }
20+ .status {
21+ padding : 10px ;
22+ border-radius : 4px ;
23+ margin : 10px 0 ;
24+ }
25+ .connected { background-color : # d4edda ; color : # 155724 ; }
26+ .disconnected { background-color : # f8d7da ; color : # 721c24 ; }
27+ .connecting { background-color : # fff3cd ; color : # 856404 ; }
28+ # messages {
29+ height : 300px ;
30+ overflow-y : auto;
31+ border : 1px solid # ddd ;
32+ padding : 10px ;
33+ background-color : # f8f9fa ;
34+ font-family : monospace;
35+ white-space : pre-wrap;
36+ }
37+ input [type = "text" ] {
38+ width : 70% ;
39+ padding : 8px ;
40+ margin : 5px ;
41+ }
42+ button {
43+ padding : 8px 16px ;
44+ margin : 5px ;
45+ cursor : pointer;
46+ }
47+ .controls {
48+ margin : 10px 0 ;
49+ }
50+ </ style >
51+ </ head >
52+ < body >
53+ < h1 > 🌊 Hydro WebSocket Test Client</ h1 >
54+
55+ < div class ="container ">
56+ < h3 > Connection</ h3 >
57+ < div >
58+ < label > WebSocket URL:</ label >
59+ < input type ="text " id ="wsUrl " value ="ws://localhost:8080 " placeholder ="ws://localhost:8080 ">
60+ < button onclick ="connect() "> Connect</ button >
61+ < button onclick ="disconnect() "> Disconnect</ button >
62+ </ div >
63+ < div id ="status " class ="status disconnected "> Disconnected</ div >
64+ </ div >
65+
66+ < div class ="container ">
67+ < h3 > Send Messages</ h3 >
68+ < div class ="controls ">
69+ < input type ="text " id ="messageInput " placeholder ="Type your message here... " onkeypress ="handleKeyPress(event) ">
70+ < button onclick ="sendMessage() "> Send Text</ button >
71+ </ div >
72+ </ div >
73+
74+ < div class ="container ">
75+ < h3 > Messages</ h3 >
76+ < div id ="messages "> </ div >
77+ < button onclick ="clearMessages() "> Clear Messages</ button >
78+ </ div >
79+
80+ < script >
81+ let ws = null ;
82+ let messageCount = 0 ;
83+
84+ function updateStatus ( message , className ) {
85+ const status = document . getElementById ( 'status' ) ;
86+ status . textContent = message ;
87+ status . className = `status ${ className } ` ;
88+ }
89+
90+ function addMessage ( message , type = 'info' ) {
91+ const messages = document . getElementById ( 'messages' ) ;
92+ const timestamp = new Date ( ) . toLocaleTimeString ( ) ;
93+ const prefix = type === 'sent' ? '→ SENT' :
94+ type === 'received' ? '← RECV' :
95+ type === 'error' ? '✗ ERROR' :
96+ type === 'info' ? 'ℹ INFO' : '• ' ;
97+
98+ messages . textContent += `[${ timestamp } ] ${ prefix } : ${ message } \n` ;
99+ messages . scrollTop = messages . scrollHeight ;
100+ }
101+
102+ function connect ( ) {
103+ const url = document . getElementById ( 'wsUrl' ) . value ;
104+
105+ if ( ws && ws . readyState === WebSocket . OPEN ) {
106+ addMessage ( 'Already connected' , 'info' ) ;
107+ return ;
108+ }
109+
110+ updateStatus ( 'Connecting...' , 'connecting' ) ;
111+ addMessage ( `Connecting to ${ url } ` , 'info' ) ;
112+
113+ ws = new WebSocket ( url ) ;
114+
115+ ws . onopen = function ( event ) {
116+ updateStatus ( 'Connected' , 'connected' ) ;
117+ addMessage ( 'WebSocket connection established' , 'info' ) ;
118+ } ;
119+
120+ ws . onmessage = function ( event ) {
121+ messageCount ++ ;
122+ if ( event . data instanceof Blob ) {
123+ // Handle binary data
124+ event . data . text ( ) . then ( text => {
125+ addMessage ( `Binary message: ${ text } ` , 'received' ) ;
126+ } ) ;
127+ } else {
128+ addMessage ( event . data , 'received' ) ;
129+ }
130+ } ;
131+
132+ ws . onclose = function ( event ) {
133+ updateStatus ( 'Disconnected' , 'disconnected' ) ;
134+ addMessage ( `Connection closed (code: ${ event . code } , reason: ${ event . reason } )` , 'info' ) ;
135+ ws = null ;
136+ } ;
137+
138+ ws . onerror = function ( error ) {
139+ updateStatus ( 'Error' , 'disconnected' ) ;
140+ addMessage ( `WebSocket error: ${ error } ` , 'error' ) ;
141+ } ;
142+ }
143+
144+ function disconnect ( ) {
145+ if ( ws ) {
146+ ws . close ( ) ;
147+ addMessage ( 'Disconnecting...' , 'info' ) ;
148+ } else {
149+ addMessage ( 'Not connected' , 'info' ) ;
150+ }
151+ }
152+
153+ function sendMessage ( ) {
154+ const input = document . getElementById ( 'messageInput' ) ;
155+ const message = input . value . trim ( ) ;
156+
157+ if ( ! message ) {
158+ addMessage ( 'Please enter a message' , 'error' ) ;
159+ return ;
160+ }
161+
162+ if ( ! ws || ws . readyState !== WebSocket . OPEN ) {
163+ addMessage ( 'Not connected to WebSocket server' , 'error' ) ;
164+ return ;
165+ }
166+
167+ ws . send ( message ) ;
168+ addMessage ( message , 'sent' ) ;
169+ input . value = '' ;
170+ }
171+
172+ function clearMessages ( ) {
173+ document . getElementById ( 'messages' ) . textContent = '' ;
174+ messageCount = 0 ;
175+ }
176+
177+ function handleKeyPress ( event ) {
178+ if ( event . key === 'Enter' ) {
179+ sendMessage ( ) ;
180+ }
181+ }
182+
183+ window . onload = function ( ) {
184+ addMessage ( 'Click "Connect" to start testing the Hydro WebSocket server' , 'info' ) ;
185+ } ;
186+ </ script >
187+ </ body >
188+ </ html >
0 commit comments