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
相关产品推荐
相关产品推荐

