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

前端无法连接Gorilla WebSocket服务端,求排查原因

问题描述

基于Golang Gin框架搭配Gorilla WebSocket搭建服务端,后端代码及路由配置如下:

后端处理代码:

func WsHandler(c *gin.Context) {
    upgrader.CheckOrigin = func(r *http.Request) bool {
        return true
    }
    conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
        log.Println(err)
        return
    }
    client := wsserver.Client{
        Id:         wsserver.AutoId(),
        Connection: conn,
        IsConnect:  true,
        MessageCh:  make(chan wsserver.WsMessage),
    }
    global.GD_WS.AddClient(client)
    // defer conn.Close()
    fmt.Println("New Client is connected, total: ", len(global.GD_WS.Clients))
    go handleReciveMsg(client)
    go global.GD_WS.PublishNew(client)

}

路由配置:

func initWebsocketRouter(Router *gin.RouterGroup) {
    Router.GET("ws",apis.WsHandler)
}

最终路由路径为/system/ws。

使用浏览器原生WebSocket API连接时失败,错误信息仅显示:

WebSocket connection to 'ws://127.0.0.1:6666/system/ws' failed:

但使用Node.js的websocket客户端库却能正常连接,Node.js代码如下:

var WebSocketClient = require('websocket').client;

var client = new WebSocketClient();

client.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
});

client.on('connect', function(connection) {
    connection.on('error', function(error) {
        console.log("Connection Error: " + error.toString());
    });
    connection.on('close', function() {
        console.log('echo-protocol Connection Closed');
    });
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log("Received: '" + message.utf8Data + "'");
        }
    });
    connection.send('{"action":"subscribe","topic":"coin"}')
    connection.send('{"action":"subscribe","topic":"gas"}')
});

client.connect('ws://localhost:6666/system/ws');

为何浏览器端连接失败,但Node.js客户端能正常连接?


可能的原因及解决方案

1. CORS中间件拦截握手请求

虽然你设置了upgrader.CheckOrigin = func(r *http.Request) bool { return true },但如果Gin应用全局配置了CORS中间件,可能会拦截WebSocket的握手请求(需要允许特定头和方法)。

调整CORS中间件配置,确保包含WebSocket握手所需的字段:

corsConfig := cors.DefaultConfig()
corsConfig.AllowOrigins = []string{"*"} // 根据实际业务调整允许的源
corsConfig.AllowMethods = []string{"GET", "OPTIONS"}
corsConfig.AllowHeaders = []string{"Upgrade", "Connection", "Origin"}
router.Use(cors.New(corsConfig))

2. 浏览器错误信息未完整捕获

当前前端onerror只打印了简单的"error",无法获取详细错误。修改代码打印完整错误对象:

const wsInit = () => {
    if (!window.WebSocket) {
        console.error('浏览器不支持WebSocket');
        return;
    }
    const ws = new WebSocket('ws://127.0.0.1:6666/system/ws');
    ws.onopen = function () {
        console.log('success!');
        ws.send('startting...');
    };
    ws.onclose = function () {
        console.log('close');
    };
    ws.onerror = function (event) {
        console.error('WebSocket连接错误详情:', event);
    };
    ws.onmessage = function (e) {
        console.log(e.data);
    };
};
wsInit();

通过完整错误信息可以定位具体问题,比如证书、头信息不匹配等。

3. 服务端请求未到达处理函数

在WsHandler开头添加日志,确认请求是否被路由正确转发:

func WsHandler(c *gin.Context) {
    log.Println("收到WebSocket握手请求")
    // 后续原有代码...
}

如果日志未输出,说明请求被前置中间件(如权限校验、路由前缀错误)拦截,需要排查全局中间件或路由配置。

4. 浏览器环境干扰

  • 尝试使用无痕模式测试,避免缓存或扩展(如广告拦截器、安全插件)干扰;
  • 替换连接地址为ws://localhost:6666/system/ws,排除127.0.0.1和localhost的解析差异问题。

5. 服务端Upgrade错误日志未输出

确保服务端日志级别足够,能打印upgrader.Upgrade的错误详情。可以将log.Println(err)替换为更详细的日志输出,比如:

if err != nil {
    log.Printf("WebSocket升级失败: %v", err)
    return
}

通过错误详情判断是头信息错误、协议不匹配还是其他问题。

内容的提问来源于stack exchange,提问作者THJA JUNGLE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:50:19