You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Docker+React(create-react-app)环境下http-proxy-middleware配置WebSocket失败问题

解决React本地开发环境中WebSocket代理配置问题

结合你的技术栈(create-react-app + http-proxy-middleware + Docker),我帮你梳理下WebSocket连接失败的核心问题和解决方案:

1. 修正http-proxy-middleware的WebSocket代理配置

你的API代理正常,但WebSocket代理需要额外处理HTTP升级事件,同时确保路径匹配目标服务器的端点。调整setupProxy.js如下:

const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
  // 保留正常的API代理
  app.use('/api/v4/', createProxyMiddleware({ 
    target: 'http://drf:8081', 
    changeOrigin: true 
  }));

  // 优化WebSocket代理配置
  const wsProxy = createProxyMiddleware({
    target: 'ws://asgi-server:8082',
    changeOrigin: true,
    ws: true,
    // 关键:如果你的ASGI服务器的WebSocket端点路径是/ws/users/(而不是带/api/v4前缀),需要路径重写
    // 如果目标端点就是/api/v4/ws/users/,可以删除这一行
    pathRewrite: { '^/api/v4/ws/users/': '/ws/users/' },
    // 确保代理正确处理WebSocket的HTTP升级请求
    onUpgrade: (req, socket, head) => {
      wsProxy.upgrade(req, socket, head);
    }
  });

  app.use('/api/v4/ws/users/', wsProxy);
};

这里的核心是onUpgrade回调,它确保webpack-dev-server把WebSocket的升级请求正确转发到目标ASGI服务器。另外pathRewrite要根据你的ASGI服务器实际的WebSocket端点路径调整——如果目标服务器直接监听/api/v4/ws/users/,就不需要这一行。

2. 确认Docker容器的网络连通性

因为你用Docker部署服务,要确保React开发容器和asgi-server容器在同一个Docker网络中:

  • 检查docker-compose.yml,确保所有服务(包括React dev server、drf、asgi-server)都加入同一个自定义网络(比如networks: app-network
  • 确认asgi-server服务的端口8082没有被其他容器占用,且容器内的服务确实在监听8082端口
  • 可以在React容器内执行curl ws://asgi-server:8082/api/v4/ws/users/(根据实际路径调整),测试是否能连通目标WebSocket服务

3. 避免Webpack Dev Server的WebSocket冲突

create-react-app的webpack-dev-server本身会用一个WebSocket做热重载,虽然你的业务WebSocket路径不同,但有时候还是会有干扰。可以通过环境变量修改WDS的WebSocket路径,避免冲突:

在项目根目录的.env文件中添加:

WDS_SOCKET_PATH=/ws/wds

这样WDS的热重载WebSocket会使用/ws/wds路径,和你的业务WebSocket完全分离,不会互相干扰。

4. 添加WebSocket客户端的错误调试

在你的webSocketService中添加错误和关闭监听,方便排查具体问题:

connect() {
  if (!this.webSocket) {
    console.log('CONNECT WS START');
    const wsProtocol = window.location.protocol === 'http:' ? 'ws:' : 'wss:';
    this.webSocket = new WebSocket(
      `${wsProtocol}//${window.location.host}/api/v4/ws/users/`
    );
    
    // 添加错误监听,打印具体错误信息
    this.webSocket.onerror = (error) => {
      console.error('WebSocket连接错误:', error);
    };
    
    // 添加关闭监听,便于排查断开原因
    this.webSocket.onclose = (event) => {
      console.log('WebSocket连接关闭:', event.code, event.reason);
      // 可选:添加重连逻辑
      this.webSocket = null;
    };
    
    this.addListeners();
  }
}

这样你能在浏览器控制台看到更详细的错误信息,比如是连接超时、404还是502错误,帮助定位问题。

5. 用浏览器Network面板调试请求

打开Chrome/Firefox的开发者工具,切换到Network标签,选择WS分类,然后触发WebSocket连接:

  • 查看连接请求的状态码:如果是502 Bad Gateway,说明代理无法连接到目标ASGI服务器(检查Docker网络或目标服务状态);如果是404 Not Found,说明路径不匹配(调整pathRewrite
  • 查看请求头中的UpgradeConnection字段是否为websocketUpgrade,确认代理正确转发了这些头信息

按照以上步骤调整后,你的WebSocket代理应该能正常工作了。

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

火山引擎 最新活动