You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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快速测试服务端响应:
    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
    
    若返回101状态码,说明服务端逻辑正常,问题出在客户端;若仍返回426,继续排查服务端。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:57:49