fix: round 10 critical fixes - WebSocket race, rate limiting, XSS protection, Caddyfile, and input validation

This commit is contained in:
2026-05-20 17:59:22 +08:00
parent a5b5713b29
commit 20cdcc748e
10 changed files with 336 additions and 25 deletions
+45 -3
View File
@@ -236,17 +236,59 @@ func (h *Hub) Run() {
client.UserID, client.SessionID, len(h.clients))
case message := <-h.broadcast:
// 两阶段广播:Phase 1 在 RLock 下收集失效客户端,Phase 2 在 Lock 下清理
var staleClients []*Client
h.mu.RLock()
for client := range h.clients {
select {
case client.Send <- message:
default:
// 客户端发送通道已满,跳过
close(client.Send)
delete(h.clients, client)
// 客户端发送通道已满,标记为失效
staleClients = append(staleClients, client)
}
}
h.mu.RUnlock()
// Phase 2: 在写锁下清理失效客户端
if len(staleClients) > 0 {
h.mu.Lock()
for _, client := range staleClients {
// 二次检查:客户端可能已被 unregister 移除
if _, ok := h.clients[client]; !ok {
continue
}
delete(h.clients, client)
close(client.Send)
// 清理用户索引
if h.userClients[client.UserID] != nil {
delete(h.userClients[client.UserID], client)
if len(h.userClients[client.UserID]) == 0 {
delete(h.userClients, client.UserID)
}
}
// 检查该 session 是否还有其他连接
hasOtherConn := false
if clients, ok := h.userClients[client.UserID]; ok {
for c := range clients {
if c.SessionID == client.SessionID {
hasOtherConn = true
break
}
}
}
if !hasOtherConn {
if s, ok := h.sessions[client.SessionID]; ok {
s.State = "idle"
}
}
}
h.mu.Unlock()
log.Printf("[WS] 广播清理 %d 个失效客户端 (当前连接数: %d)",
len(staleClients), len(h.clients))
}
}
}
}