Fiber原生不支持WebSocket服务端,必须用github.com/gofiber/contrib/websocket包;c.IsWebSocket()仅校验握手头,后续帧处理、心跳、生命周期需手动实现,易panic或丢消息;websocket.New()已封装gorilla/websocket并自动处理升级、跨域、上下文透传,路由须注册为app.Get("/ws", websocket.New(handler)),handler签名为func(*websocket.Conn)。

别用 c.IsWebSocket() 自己升级,也别手写 Upgrade 逻辑——Fiber 原生不支持 WebSocket 服务端,c.IsWebSocket() 只校验握手头,后续帧读写、心跳、连接生命周期全得你手写,极易 panic 或丢消息。
必须用 github.com/gofiber/contrib/websocket
这个包封装了 gorilla/websocket,自动处理连接升级、跨域校验、上下文透传;裸用 gorilla 需手动实现中间件、header 解析及用户信息传递,会导致 c.Locals 为空、跨域拦截或鉴权失效。
-
websocket.New()内部已调用http.Hijacker和Upgrader.Upgrade(),确保返回 101 状态和合法连接 - 注册路由必须是
app.Get("/ws", websocket.New(handler)),不能用app.Use或裸app.Get+ 手动升级 - handler 签名是
func(*websocket.Conn),不是*fiber.Ctx,进来的那一刻原始 HTTP 上下文就不可读了
websocket.New() 初始化时必须改的三个配置项
默认参数对生产环境极不友好,不改必出问题:
-
CheckOrigin默认为nil,即拒绝所有跨域请求;开发时前端跑在localhost:5173,必须显式设为func(r *http.Request) bool { return true } -
HandshakeTimeout默认 45 秒,但 Nginx 常设为 10–15 秒超时,建议设为10 * time.Second,否则握手被中间件截断 -
MaxMessageSize默认 1MB;若业务要传日志流、二进制附件或大 JSON,需提前调大,否则c.ReadMessage()报错websocket: close 1009 (message too big)
用户身份怎么安全透传进 WebSocket 连接
WebSocket 连接一旦升级,就脱离 HTTP 请求上下文,c.Get("Authorization")、c.Cookies() 全部失效。不能在 websocket.New() 闭包里临时解析 token——header 已不可读。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 必须用中间件提前鉴权:在
app.Use("/ws", ...)中解析 JWT 或 Cookie,验证通过后调用c.Locals("user_id", uid) - 该中间件必须放在
websocket.New()调用之前,且只能读取请求头和 URL(c.QueryParam、c.Get可用,c.Body()不可用) - 路径带参数如
/ws/:room/:id时,注意StrictRouting: true默认开启,/ws/chat/101/(尾斜杠)会被 404,前端 URL 必须严格不带尾部斜杠
推送消息不能在 HTTP Handler 里直接调 c.WriteMessage()
常见错误是收到 POST /api/push 后遍历所有 *websocket.Conn 并挨个 WriteMessage(),结果不是 panic 就是 goroutine 堵死。
-
*websocket.Conn不是并发安全的,多个 goroutine 同时写会冲突或静默断连 - 某个客户端网络卡住,
WriteMessage()会阻塞当前 goroutine,拖垮整个广播流程 - 正确做法是用广播 channel 解耦:HTTP 接口只往
broadcast = make(chan []byte, 100)写数据,由独立hub.run()goroutine 拉取、过滤、分发 - 每个连接在
websocket.New回调中启动读/写 goroutine,并注册进全局sync.Map管理的clients
最常被忽略的是:连接建立前的中间件必须做完所有鉴权和参数提取,之后就再也拿不到 header、query、cookie;而连接建立后的消息广播,又必须彻底避开 HTTP handler 生命周期——这两处边界一旦模糊,问题就藏得深、复现难。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










