chat: fix ws error
Kim committed
Oct 21, 2025 at 16:40 UTC
9fbefa935f02534c2e96423c1bf1a7ad02755f7e
2 files changed
+29
-7
cmd/example_chat/view.go
+22
-7
@@ -168,10 +168,11 @@ var indexTmpl = template.Must(template.New("chat").Parse(`<!DOCTYPE html>
168
promptEl.textContent = nick + '@chat:~$';
169
}
170
function randomNick(){
171
- const adjs = ['brisk','calm','clever','daring','eager','gentle','merry','rapid','vivid','bright'];
172
- const animals = ['fox','lion','panda','otter','eagle','whale','koala','lynx','squid','yak'];
173
- const a = adjs[Math.floor(Math.random()*adjs.length)];
174
- const b = animals[Math.floor(Math.random()*animals.length)];
171
+ // Programming-meme themed nickname
172
+ const techs = ['gopher','rustacean','nixer','unix','kernel','docker','kube','vim','emacs','tmux','nvim','git','linux','bsd','wasm','grpc','lambda','pointer','monad','segfault','null','byte','packet','devops','cli'];
173
+ const roles = ['wizard','hacker','guru','daemon','runner','scripter','shell','warrior','artisan','smith'];
174
+ const a = techs[Math.floor(Math.random()*techs.length)];
175
+ const b = roles[Math.floor(Math.random()*roles.length)];
176
const id = Math.random().toString(36).slice(2,6);
177
return a + '-' + b + '-' + id;
178
}
@@ -193,12 +194,25 @@ var indexTmpl = template.Must(template.New("chat").Parse(`<!DOCTYPE html>
194
user.focus();
195
});
196
197
+ // Stable color per nickname
198
+ const PALETTE = ['#60a5fa','#22c55e','#f59e0b','#ef4444','#a78bfa','#14b8a6','#eab308','#f472b6','#8b5cf6','#06b6d4'];
199
+ function hashNick(s){
200
+ let h = 0;
201
+ for (let i = 0; i < s.length; i++) { h = ((h << 5) - h) + s.charCodeAt(i); h |= 0; }
202
+ return (h >>> 0);
203
+ }
204
+ function colorFor(nick){
205
+ const idx = hashNick(nick || 'anon') % PALETTE.length;
206
+ return PALETTE[idx];
207
+ }
208
function append(msg){
209
const div = document.createElement('div');
210
div.className = 'line';
211
const ts = new Date(msg.ts).toLocaleTimeString();
200
- div.innerHTML = '<span class="ts">[' + ts + ']</span> <span class="usr">' +
201
- (msg.user || 'anon') + '</span>: ' + escapeHTML(msg.text || '');
212
+ const nick = (msg.user || 'anon');
213
+ const color = colorFor(nick);
214
+ div.innerHTML = '<span class="ts">[' + ts + ']</span> <span class="usr" style="color:' + color + '">' +
215
+ nick + '</span>: ' + escapeHTML(msg.text || '');
216
log.appendChild(div);
217
log.scrollTop = log.scrollHeight;
218
}
@@ -207,7 +221,8 @@ var indexTmpl = template.Must(template.New("chat").Parse(`<!DOCTYPE html>
221
}
222
223
const wsProto = location.protocol === 'https:' ? 'wss' : 'ws';
210
- const ws = new WebSocket(wsProto + '://' + location.host + location.pathname + 'ws');
224
+ const basePath = location.pathname.endsWith('/') ? location.pathname : (location.pathname + '/');
225
+ const ws = new WebSocket(wsProto + '://' + location.host + basePath + 'ws');
226
ws.onmessage = (e) => { try{ append(JSON.parse(e.data)); }catch(_){ } };
227
function send(){
228
const payload = { user: (user.value || 'anon'), text: cmd.value.trim() };
relaydns/director.go
+7
@@ -226,6 +226,13 @@ func (d *Director) ProxyHTTP(w http.ResponseWriter, r *http.Request, peerID, pat
226
if err := resp.Write(clientBuf); err == nil {
227
_ = clientBuf.Flush()
228
}
229
+ // Flush any bytes already buffered by http.ReadResponse's bufio.Reader
230
+ if n := br.Buffered(); n > 0 {
231
+ tmp := make([]byte, n)
232
+ if _, err := io.ReadFull(br, tmp); err == nil {
233
+ _, _ = clientConn.Write(tmp)
234
+ }
235
+ }
236
// Raw byte tunnel between client and upstream stream
237
go io.Copy(s, clientConn)
238
io.Copy(clientConn, s)