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

Vue.js+Vite开发SPA无法连接WebSocket端点的问题排查

问题:Vue.js + Vite开发SPA时WebSocket连接失败(CLI工具可正常连接)

问题背景

使用Vue.js + Vite开发单页应用,后端已配置WebSocket端点。通过CLI工具websocat可正常连接该端点,但用JavaScript代码连接时,Firefox和Chrome均提示连接错误。证书来自Let's Encrypt,暂不确定是否与此问题相关。

Vite开发服务器代理配置

server: {
      // 允许IP访问
      host: "portal-local.itps.xxx.com",
      // 应用端口 (默认:3000)
      port: Number(env.VITE_APP_PORT),
      // 运行是否自动打开浏览器
      open: true,
      https: {
        key: fs.readFileSync(
          "/home/ggfan/2-work/git/itps/1A-IaaS-Manifests/kubernetes/1.27/ssl/certs/itps.xxx.com/privkey.pem"
        ),
        cert: fs.readFileSync(
          "/home/ggfan/2-work/git/itps/1A-IaaS-Manifests/kubernetes/1.27/ssl/certs/itps.xxx.com/fullchain.pem"
        ),
      },
      proxy: {
        /**
         * 反向代理解决跨域配置
         * http://localhost:3000/dev-api/users (F12可见请求路径) => http://localhost:8989/users (实际请求后端 API 路径)
         *
         * env.VITE_APP_BASE_API: /dev-api
         * env.VITE_APP_API_URL: http://localhost:8989
         */
        /*
        [env.VITE_APP_BASE_API]: {
          changeOrigin: true,
          target: "http://localhost:8080",
          rewrite: (path) =>
            path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
        },
        */
        ["/oauth2"]: {
          changeOrigin: true,
          target: "https://api.itps.xxx.com",
          // secure: false,
          rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
          /*
          cookieDomainRewrite: {
            "itps.xxx.com": "localhost",
          },
          */
        },
        ["/pus"]: {
          changeOrigin: true,
          target: "http://localhost:8080",
          // secure: false,
          rewrite: (path) => path.replace(/^\/pus/, ""),
          /*
          cookieDomainRewrite: {
            "itps.xxx.com": "localhost",
          },
          */
          configure: proxyConfig,
        },
        ["/ws"]: {
          changeOrigin: true,
          target: "http://localhost:8080",
          ws: true,
          secure: false,
          rewrite: (path) => path.replace(/^\/ws/, ""),
          configure: proxyConfig,
        },
      },
    }

websocat连接状态

websocat可正常连接后端WebSocket端点,连接状态无异常。

前端TypeScript连接代码

const ws = new WebSocket("wss://portal-local.itps.xxx.com:3000/ws/export/sea/users")
ws.onopen = () => {
  ws.send("{}")
}
ws.onmessage = async (event) => {
  console.log(event.data)
  await writable.write(event.data)
}
ws.onclose = async (event) => {
  await writable.close()
}

Chrome报错信息

SEAExportDialog.vue:104 WebSocket connection to 'wss://portal-local.itps.xxx.com:3000/ws/export/sea/users' failed: 

排查更新(Wireshark抓包分析)

通过Wireshark抓包发现,Vite代理服务器返回403 Forbidden状态码:

Frame 22: 844 bytes on wire (6752 bits), 844 bytes captured (6752 bits) on interface lo, id 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 38478, Dst Port: 3000, Seq: 683, Ack: 4150, Len: 778
Transport Layer Security
Hypertext Transfer Protocol
    GET /ws/export/sea/users HTTP/1.1\r\n
        [Expert Info (Chat/Sequence): GET /ws/export/sea/users HTTP/1.1\r\n]
            [GET /ws/export/sea/users HTTP/1.1\r\n]
            [Severity level: Chat]
            [Group: Sequence]
        Request Method: GET
        Request URI: /ws/export/sea/users
        Request Version: HTTP/1.1
    Host: portal-local.itps.xxx.com:3000\r\n
    Connection: Upgrade\r\n
    Pragma: no-cache\r\n
    Cache-Control: no-cache\r\n
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\r\n
    Upgrade: websocket\r\n
    Origin: https://portal-local.itps.xxx.com:3000\r\n
    Sec-WebSocket-Version: 13\r\n
    Accept-Encoding: gzip, deflate, br, zstd\r\n
    Accept-Language: zh-CN,zh;q=0.9\r\n
    Cookie: _oauth2_proxy=X29hdXRoMl9wcm94eS00ZWU3OTM2NTIwYWYxNjBjNjZlNGQ4ODJkNTA0OGE4Yy5NM0FOUzVJRlBTV2JkN1g2Zlh6RWtB|1713431461|XkFGp00nkvsob926le3vxJ61wpGV44gtE1GeZcl4eEg=\r\n
        Cookie pair: _oauth2_proxy=X29hdXRoMl9wcm94eS00ZWU3OTM2NTIwYWYxNjBjNjZlNGQ4ODJkNTA0OGE4Yy5NM0FOUzVJRlBTV2JkN1g2Zlh6RWtB|1713431461|XkFGp00nkvsob926le3vxJ61wpGV44gtE1GeZcl4eEg=
    Sec-WebSocket-Key: FLMsmXSIxrT0bV1TA8yd/Q==\r\n
    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n
    Sec-WebSocket-Protocol: WebSocket\r\n
    \r\n
    [Full request URI: https://portal-local.itps.xxx.com:3000/ws/export/sea/users]
    [HTTP request 1/1]
    [Response in frame: 24]

Frame 24: 161 bytes on wire (1288 bits), 161 bytes captured (1288 bits) on interface lo, id 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 3000, Dst Port: 38478, Seq: 4724, Ack: 1461, Len: 95
Transport Layer Security
Hypertext Transfer Protocol
    HTTP/1.1 403 \r\n
        [Expert Info (Chat/Sequence): HTTP/1.1 403 \r\n]
            [HTTP/1.1 403 \r\n]
            [Severity level: Chat]
            [Group: Sequence]
        Response Version: HTTP/1.1
        Status Code: 403
        [Status Code Description: Forbidden]
    content-length: 0\r\n
        [Content length: 0]
    date: Thu, 18 Apr 2024 09:24:37 GMT\r\n
    \r\n
    [HTTP response 1/1]
    [Time since request: 0.011595626 seconds]
    [Request in frame: 22]
    [Request URI: https://portal-local.itps.xxx.com:3000/ws/export/sea/users]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 16:55:02