Node.js HTTP模块无法接收WebSocket请求(使用https-proxy-agent)
我来帮你分析下这个问题,以及如何解决它:
问题核心原因
WebSocket 请求本质是基于 HTTP 协议的握手请求,你的 HTTP 服务器没收到请求,大概率是两个问题:
- 客户端的代理配置有误,导致请求根本没发到你的 9999 端口
- 就算请求到达了,你的 HTTP 服务器没有处理 WebSocket 特有的
upgrade事件,握手失败后客户端会立刻断开,你可能没来得及看到日志
解决方案
我们需要先让 HTTP 服务器正确识别并处理 WebSocket 握手,再修正客户端的代理配置。
1. 修复 HTTP 服务器,支持 WebSocket 转发
原始代码只监听了普通 HTTP 请求的request事件,但 WebSocket 握手会触发upgrade事件,我们需要单独处理这个事件来完成转发:
const http = require('http'); const WebSocket = require('ws'); // 创建基础 HTTP 服务器 const server = http.createServer((req, res) => { console.log('收到普通 HTTP 请求:', req.method, req.url); res.writeHead(200); res.end('这是 HTTP 服务器'); }); // 处理 WebSocket 握手与转发 server.on('upgrade', (req, socket, head) => { console.log('收到 WebSocket 握手请求:', req.url); // 连接到目标端口的 WebSocket 服务(示例目标端口为 8080) const targetWs = new WebSocket(`ws://localhost:8080${req.url}`); // 完成客户端握手响应 targetWs.on('open', () => { socket.write( `HTTP/1.1 101 Switching Protocols\r\n` + `Upgrade: websocket\r\n` + `Connection: Upgrade\r\n` + `Sec-WebSocket-Accept: ${req.headers['sec-websocket-accept']}\r\n\r\n` ); // 双向转发数据 socket.pipe(targetWs); targetWs.pipe(socket); }); // 错误处理,避免连接泄漏 targetWs.on('error', (err) => { console.error('连接目标 WebSocket 失败:', err); socket.destroy(); }); socket.on('error', (err) => { console.error('客户端连接错误:', err); targetWs.close(); }); }); server.listen(9999, () => { console.log('HTTP 服务器监听在 9999 端口'); });
如果你想更简洁,可以用ws-proxy库简化转发逻辑:
先安装依赖:
npm install ws-proxy
再修改服务器代码:
const http = require('http'); const { createProxy } = require('ws-proxy'); const server = http.createServer((req, res) => { console.log('收到普通 HTTP 请求:', req.method, req.url); res.end('Hello HTTP'); }); // 创建 WebSocket 代理,转发到目标端口 8080 const proxy = createProxy({ target: 'ws://localhost:8080' }); server.on('upgrade', proxy.upgrade); server.listen(9999);
2. 修正客户端代理配置
你的客户端用了HttpsProxyAgent,但如果你的转发服务器是 HTTP 协议(而非 HTTPS),应该用HttpProxyAgent,正确代码如下:
const WebSocket = require('ws'); const { HttpProxyAgent } = require('http-proxy-agent'); // 配置代理指向你的 9999 端口服务器 const agent = new HttpProxyAgent('http://localhost:9999'); // 通过代理连接目标 WebSocket 服务 const ws = new WebSocket('ws://localhost:8080/your-path', { agent }); ws.on('open', () => { console.log('WebSocket 连接成功'); ws.send('Hello from client'); }); ws.on('message', (data) => { console.log('收到服务器消息:', data.toString()); }); ws.on('error', (err) => { console.error('WebSocket 错误:', err); }); ws.on('close', () => { console.log('WebSocket 连接关闭'); });
关键注意事项
- 只有当你的转发服务器是 HTTPS 协议时,才需要用
HttpsProxyAgent,否则用HttpProxyAgent - WebSocket 请求不会触发
createServer的回调函数,必须监听upgrade事件才能捕获 - 日志要打印在
upgrade事件处理逻辑里,才能看到 WebSocket 请求的信息
这样修改后,你的 HTTP 服务器就能正常接收并转发 WebSocket 请求了。
内容的提问来源于stack exchange,提问作者Aero Wang
相关产品推荐
相关产品推荐

