Golang Fiber框架WebSocket遇426 Upgrade Required问题求助
Fiber WebSocket 426 Upgrade Required 问题排查与修复
问题说明
在Golang Fiber框架中使用WebSocket时,客户端请求返回426 Upgrade Required状态码,已注册的WebSocket升级中间件日志显示正常,但请求始终无法抵达WebSocket处理函数。目前尚未编写WebSocket功能实现代码,因为请求根本没进入处理环节。曾尝试在中间件手动设置101状态码、Upgrade: Websocket和Connection: Upgrade头,问题未解决。
现有代码片段
中间件注册
App.Use("/api/v1/claim/ws", middleware.WebsocketUpgrade)
中间件代码
func WebsocketUpgrade(c *fiber.Ctx) error { if websocket.IsWebSocketUpgrade(c) { c.Locals("websocket connected", true) return c.Next() } return fiber.ErrUpgradeRequired }
处理器注册
claimGroup.Get("/ws/employee/:id", timeout.NewWithContext(handler.WebSocketClaimsCounterHandler(s.serv, s.log, cfg.Server.WS), cfg.Server.AppReadTimeout))
处理器代码
func WebSocketClaimsCounterHandler(s StaffService, log *logger.Logger, cfg config.WebSocket) fiber.Handler { cfgWS := websocket.Config{ HandshakeTimeout: cfg.HandshakeTimeout, Origins: cfg.Origins, ReadBufferSize: cfg.ReadBufferSize, WriteBufferSize: cfg.WriteBufferSize, } return websocket.New(func(*websocket.Conn), cfgWS) }
排查与修复步骤
1. 确认路由匹配有效性
中间件注册路径为/api/v1/claim/ws,处理器路径为/ws/employee/:id,需先确认claimGroup的前缀是否为/api/v1/claim,确保处理器完整路径是/api/v1/claim/ws/employee/:id。
- 建议在中间件中添加日志打印请求路径,验证请求是否进入中间件:
log.Println("当前请求路径:", c.Path()) - 若请求未进入中间件,可将中间件注册路径改为
/api/v1/claim/ws/(带尾斜杠),确保前缀匹配覆盖后续子路径。
2. 检查客户端请求头合规性
websocket.IsWebSocketUpgrade(c)的判断依赖客户端发送标准的WebSocket升级头:
- 必须包含
Upgrade: websocket - 必须包含
Connection: Upgrade - 浏览器端可通过开发者工具的网络面板查看请求头;自定义客户端需手动设置这两个头。
- 可用curl快速测试服务端响应:
若返回101状态码,说明服务端逻辑正常,问题出在客户端;若仍返回426,继续排查服务端。curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" http://localhost:3000/api/v1/claim/ws/employee/123
3. 修正处理器函数写法错误
当前处理器中websocket.New的调用存在语法问题:第一个参数要求是func(*websocket.Conn) error类型的处理函数,现有写法缺少参数名与函数体,会导致编译或运行时错误。正确写法示例:
func WebSocketClaimsCounterHandler(s StaffService, log *logger.Logger, cfg config.WebSocket) fiber.Handler { cfgWS := websocket.Config{ HandshakeTimeout: cfg.HandshakeTimeout, Origins: cfg.Origins, ReadBufferSize: cfg.ReadBufferSize, WriteBufferSize: cfg.WriteBufferSize, } return websocket.New(func(conn *websocket.Conn) error { defer conn.Close() // 此处编写WebSocket消息处理逻辑,示例为echo功能 for { msgType, msg, err := conn.ReadMessage() if err != nil { log.Println("读取消息失败:", err) break } if err = conn.WriteMessage(msgType, msg); err != nil { log.Println("发送消息失败:", err) break } } return nil }, cfgWS) }
4. 排查反向代理配置(若有)
若服务部署在Nginx等反向代理后,需配置代理支持WebSocket转发,否则升级头会被丢失:
location /api/v1/claim/ws { proxy_pass http://你的后端服务地址; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }
5. 验证中间件头判断逻辑
在中间件中打印所有请求头,确认是否收到正确的升级头:
log.Println("请求头信息:", c.GetReqHeaders())
若头信息正确但websocket.IsWebSocketUpgrade(c)返回false,尝试升级Fiber与websocket依赖包到最新版本。
内容的提问来源于stack exchange,提问作者Yehor Tverytinov
相关产品推荐
相关产品推荐

