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

Node.js中通过http-proxy代理WebSocket请求前获取握手数据

在http-proxy中获取Socket.io客户端的握手auth数据

要在http-proxy代理请求前拿到Socket.io客户端通过auth字段发送的握手数据,得针对**Polling(HTTP)和WebSocket(Upgrade)**两种传输方式分别处理——因为它们的auth数据传递形式完全不同:


1. 处理Polling传输的HTTP请求

Polling模式下,Socket.io的auth数据会以JSON格式嵌套在POST请求的请求体里(格式类似EIO=4&transport=polling&b={"auth":{"token":"abcd","id":"someid"}})。你可以在服务器的请求处理逻辑中先解析请求体,再执行代理:

const http = require('http');
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
const targetServer = 'http://你的目标服务器地址';

const server = http.createServer((req, res) => {
  // 只处理Socket.io的Polling POST请求
  if (req.url.startsWith('/socket.io/') && req.method === 'POST') {
    let rawBody = '';
    req.on('data', chunk => rawBody += chunk.toString());
    req.on('end', () => {
      try {
        const params = new URLSearchParams(rawBody);
        const payload = JSON.parse(params.get('b'));
        // 提取auth数据
        if (payload.auth) {
          const { token, id } = payload.auth;
          console.log('Polling握手auth:', token, id);
          // 这里可以加验证逻辑,比如token无效就返回401
          // if (!validToken(token)) return res.writeHead(401).end();
        }
      } catch (err) {
        console.error('解析Polling请求体失败:', err);
      }
      // 继续代理请求
      proxy.web(req, res, { target: targetServer });
    });
  } else {
    // 非Socket.io请求直接代理
    proxy.web(req, res, { target: targetServer });
  }
});

2. 处理WebSocket的Upgrade请求

WebSocket握手时,Socket.io会把auth对象JSON序列化后编码,放在请求URL的查询参数中(参数名就是auth)。你需要解析req.url里的查询参数来提取数据:

server.on('upgrade', (req, socket, head) => {
  const queryStr = req.url.split('?')[1];
  if (!queryStr) {
    // 无查询参数,直接代理或断开
    return proxy.ws(req, socket, head, { target: targetServer.replace('http', 'ws') });
  }

  const urlParams = new URLSearchParams(queryStr);
  const authEncoded = urlParams.get('auth');
  if (authEncoded) {
    try {
      const authData = JSON.parse(decodeURIComponent(authEncoded));
      const { token, id } = authData;
      console.log('WebSocket握手auth:', token, id);
      // 验证失败的话直接断开连接
      // if (!validToken(token)) return socket.destroy();
    } catch (err) {
      console.error('解析WebSocket auth失败:', err);
    }
  }
  // 代理WebSocket请求
  proxy.ws(req, socket, head, { target: targetServer.replace('http', 'ws') });
});

// 启动服务器
server.listen(3000);

关键注意事项

  • 不同Socket.io版本的参数格式可能略有差异,比如旧版本可能把auth放在Authorization请求头里,建议和客户端版本对齐。
  • 解析过程一定要加异常捕获,避免非法请求导致服务器崩溃。
  • 如果验证不通过,直接断开连接或返回401,不要继续代理无效请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:50:21