从 Nginx 到 express.js 上的 socket.io 的反向代理上的“无法获取”
Posted
技术标签:
【中文标题】从 Nginx 到 express.js 上的 socket.io 的反向代理上的“无法获取”【英文标题】:"Cannot GET" on reverse proxy from Nginx to socket.io on express.js 【发布时间】:2015-10-06 01:20:50 【问题描述】:我已经关注this tutorial,让 Node.js 通过私有网络在两台 Ubuntu 14.04 服务器上通过 nginx 工作(Node.js 在 myappserver 上 - 可通过私有 IP myprivatewebserver 访问并通过 mypublicappserver 公开访问 - 以及 mywebserver 上的 Nginx) .到目前为止一切正常 - 我可以通过 Nginx 访问 myprivateappserver:3000 上的 node.js 应用程序,方法是转到 http://mywebserver/node。
但是,当我尝试在 express.js 上的 socket.io 中运行 chat application 时,当我直接访问它时它可以工作 (http://mypublicappserver:3000) 但是,当我尝试通过我的 Nginx 代理访问它时 (@ 987654325@),我在浏览器和萤火虫控制台中得到“Cannot GET /node” “网络错误:404 未找到 - http://mywebserver/node”。
如果我从 mywebserver curl http://myprivateappserver:3000,我可以从我的 socket.io 应用程序中获取 index.html。
我的 /etc/nginx/sites-available/default 包含:
location /node
proxy_pass http://myprivateappserver:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
我的 index.js 是:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res)
res.sendFile(__dirname + '/index.html');
);
io.on('connection', function(socket)
console.log('a user connected');
socket.on('disconnect', function()
console.log('user disconnected');
);
socket.on('chat message', function(msg)
io.emit('chat message', msg);
);
);
http.listen(3000, function()
console.log('listening on *:3000');
);
而我的 index.html 是:
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* margin: 0; padding: 0; box-sizing: border-box;
body font: 13px Helvetica, Arial;
form background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%;
form input border: 0; padding: 10px; width: 90%; margin-right: .5%;
form button width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px;
#messages list-style-type: none; margin: 0; padding: 0;
#messages li padding: 5px 10px;
#messages li:nth-child(odd) background: #eee;
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function()
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
);
socket.on('chat message', function(msg)
$('#messages').append($('<li>').text(msg));
);
</script>
</body>
</html>
这是我第一次涉足 nginx/node/express/socket(我通常是 Apache/Cakephp 人员),所以我很可能遗漏了一些非常简单的东西,但也非常感谢任何关于如何调试的指针出错了
【问题讨论】:
【参考方案1】:我认为这样会更好:
location /node
proxy_pass http://myprivateappserver:3000/; # add "/"
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_pass加'/',然后app.get('/')也ok!
【讨论】:
【参考方案2】:location ~ /(node|socket.io)
.......
这也适用于没有“^”和“\”符号的情况。
【讨论】:
【参考方案3】:好奇的好回答。我想补充一点,如果您使用 sub_filter,则不必调整 node.js 应用程序。你的 nginx 一定是用那个模块编译的。
location ~ ^/(node|socket\.io)
#your proxy directives
sub_filter /node /;
【讨论】:
【参考方案4】:这是因为 SocketIO 默认使用/socket.io
路径,所以你需要配置 Nginx 使其不仅代理/node
请求,还代理/socket.io
:
location ~ ^/(node|socket\.io)
#your proxy directives
(顺便说一句,你好像有错别字:你写了proxypass
,但正确的形式是proxy_pass
。其他proxy
指令也是如此)
您还需要在 NodeJS 服务器文件中再执行一次编辑。替换:
app.get('/', function(req, res)
与:
app.get('/node', function(req, res)
现在应该可以了。
这不是唯一的解决方案。您也可以通过对 Nginx 配置进行一些更改来更改 SocketIO path,但上面描述的解决方案对我来说似乎是最简单的。祝你好运!
【讨论】:
非常感谢@Curious。这将花费我很长时间来为自己解决 - 我不明白代理地址与它所代理的应用程序是如何相互关联的。当我粘贴它们时,我重新插入了从 proxy_pass 等指令中删除的下划线,以免混淆到达此页面的其他人。再次感谢。 @theotherdy 不客气)代理时如何转换 URL 有多种选择,您可以阅读更多 here。下划线怎么样 - 你做了一件好事,但你错过了$httpupgrade
变量中的下划线。祝你好运:)
我想我需要做一些 Nginx 手册阅读。很好地发现了那个缺失的下划线 - 现在也添加了那个。再次感谢
万一其他人关注这个线程,我早上大部分时间都在意识到,当我的 CakePHP 应用程序由 mywebserver 提供服务时,我尝试设置一个连接: var socket = io('mywebserver/node');这被正确代理并连接到mypublicappserver:3000 但是,虽然连接在那里,但 Socket.io 认为我是说我希望通信在“节点”命名空间中,所以发出不起作用!但是更改为: var nsp=io.of('/node') 然后 nsp.on('connection', function(socket)etc. 它可以工作!
请帮助我。我不想让请求传递给我的应用程序。 ***.com/questions/39574238/…以上是关于从 Nginx 到 express.js 上的 socket.io 的反向代理上的“无法获取”的主要内容,如果未能解决你的问题,请参考以下文章
无法将多部分表单数据从 React 正确发送到 Express Js
计时器运行时,Express.js上的504 Gateway Timeout错误