使用节点 http-proxy 代理 websocket 连接

Posted

技术标签:

【中文标题】使用节点 http-proxy 代理 websocket 连接【英文标题】:Using node http-proxy to proxy websocket connections 【发布时间】:2014-03-04 23:35:43 【问题描述】:

我有一个通过 socket.io 使用 websockets 的应用程序。对于我的应用程序,我想使用单独的 HTTP 服务器为我的应用程序提供静态内容和 javascript。因此,我需要放置一个代理。

我正在使用node-http-proxy。作为起点,我的 websockets 应用程序在端口 8081 上运行。我使用以下代码将 socket.io 通信重定向到此独立服务器,同时使用 express 提供静态内容:

var http = require('http'),
    httpProxy = require('http-proxy'),
    express = require('express');

// create a server
var app = express();
var proxy = httpProxy.createProxyServer( ws: true );

// proxy HTTP GET / POST
app.get('/socket.io/*', function(req, res) 
  console.log("proxying GET request", req.url);
  proxy.web(req, res,  target: 'http://localhost:8081');
);
app.post('/socket.io/*', function(req, res) 
  console.log("proxying POST request", req.url);
  proxy.web(req, res,  target: 'http://localhost:8081');
);

// Proxy websockets
app.on('upgrade', function (req, socket, head) 
  console.log("proxying upgrade request", req.url);
  proxy.ws(req, socket, head);
);

// serve static content
app.use('/', express.static(__dirname + "/public"));

app.listen(8080);

上面的应用程序工作得很好,但是,我可以看到 socket.io 不再使用 websockets,而是回退到 XHR 轮询。

我可以通过查看代理代码中的日志来确认:

proxying GET request /socket.io/1/?t=1391781619101
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294
proxying POST request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=1391781629
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294

有谁知道如何代理网络套接字通信? node-http-proxy 中的所有示例都假设您要代理所有流量,而不是代理一些流量并为其他流量提供服务。

【问题讨论】:

我个人使用 nginx 作为 http 服务器和代理。它非常适用于 websocket 代理(这就是我从 apache 切换的原因)。 @dystroy 感谢您的提示 - 尽管我希望有一个基于节点的解决方案。这样开发人员就可以拥有反映实时部署的本地设置。 【参考方案1】:

您需要两台服务器吗?如果不是,您可以使用同一台服务器处理静态文件并监听套接字连接:

// make the http server
var express = require('express'),
    app = express(), server = require('http').createServer(app),
    io;

// serve static content
server.use('/', express.static(__dirname + '/public'));

server.listen(8080);

// listen for socket connections
io = require('socket.io').listen(server);

// socket stuff here

【讨论】:

是的,我知道我可以使用一台服务器 - 但重点是在生产中流连接将来自不同的服务器!感谢您的意见:-)【参考方案2】:

刚刚偶然发现您的问题,我看到它仍然没有回答。好吧,如果您仍在寻找解决方案... 您的代码中的问题是 app.listen(8080) 只是

的语法糖
require('http').createServer(app).listen(8080)

虽然app 本身只是一个处理函数,而不是httpServer 的实例(我个人认为应该从Express 中删除该功能以避免混淆)。 因此,您的 app.on('upgrade') 实际上从未使用过。你应该写

var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) 
  proxy.ws(req, socket, head);
);
server.listen(8080);

希望,这会有所帮助。

【讨论】:

这完美!我为浏览器同步和快速设置创建了一个要点:gist.github.com/timaschew/00ba49d3a39bc3dfbe8f

以上是关于使用节点 http-proxy 代理 websocket 连接的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# 使用 http-proxy 实现 SAP UI5 请求的代理重定向

使用http-proxy替代nginx实现反向代理

Node.js - 使用 Express 和 http-proxy 进行反向代理

Nodejs http-proxy代理实战应用

在本地设置 http-proxy 代理 (前后端分离)

节点 http-proxy:将流量转发到外部 https 站点 - 崩溃