简体   繁体   English

Node.js-Websocket在由Nginx反向代理提供服务时拒绝打开连接

[英]Node.js - Websocket refuses to open a connection when served by Nginx reverse proxy

Currently i'm trying to set up a simple chat application. 目前,我正在尝试建立一个简单的聊天应用程序。 I am using the total.js framework. 我正在使用total.js框架。 My Node.js program runs on [http]://127.0.0.1:8000/. 我的Node.js程序在[http]://127.0.0.1:8000 /上运行。 This works as long as the request URI matches the exact URI as specified in the HTML code of the loaded page. 只要请求URI与加载页面的HTML代码中指定的确切URI匹配,这就有效。 For instance going to [http]://localhost:8000/ wil load the html page, but all functionality won't work while [http]://127.0.0.1:8000 will work as expected. 例如,转到[http]:// localhost:8000 / wil加载html页面,但是[http]://127.0.0.1:8000将按预期工作时,所有功能都不起作用。

I found this out while trying to setup Nginx as a reverse proxy so i could reach it by going to [http]://127.0.0.1:80/. 我在尝试将Nginx设置为反向代理时发现了这一点,因此可以通过转到[http]://127.0.0.1:80 /来实现。 Here the html page would load, but the chat functionality woudn't work. 这里将加载html页面,但聊天功能不起作用。

This chat app is part of the total.js examples. 此聊天应用程序是total.js示例的一部分。

Here is the index.html file which creates the websocket: 这是创建websocket的index.html文件:

 <div class="mb5"> <button name="open">CONNECT</button> </div> <div> <button name="close" disabled="disabled">DISCONNECT</button> </div> <br /> <div> <input type="text" name="message" maxlength="200" style="width:500px" /> <button name="send" disabled="disabled">SEND</div> </div> <br /> <div> <textarea id="output" style="width:620px;height:300px" readonly="readonly"></textarea> </div> <br /> <div> <input type="text" value="" name="username" maxlength="20" style="width:200px" /> <button name="rename" disabled="disabled">RENAME</div> </div> <script type="text/javascript"> var socket = null; $(document).ready(function() { $('button').bind('click', function() { if (this.name === 'rename') { var value = $('input[name="username"]').val(); if (value.length > 0) socket.send(encodeURIComponent(JSON.stringify({ username: value }))); return; } if (this.name === 'send') { console.log('send'); send(); return; } if (this.name === 'open') { connect(); return; } console.log('disconnect'); disconnect(); }); }); function connect() { if (socket !== null) return; $('button[name="open"]').attr('disabled', true); $('button[name="close"],button[name="send"],button[name="rename"]').attr('disabled', false); socket = new WebSocket('ws://127.0.0.1:8000/'); socket.onopen = function() { console.log('open'); }; socket.onmessage = function(e) { var el = $('#output'); var m = JSON.parse(decodeURIComponent(e.data)).message; el.val(m + '\\n' + el.val()); }; socket.onclose = function(e) { // e.reason ==> total.js client.close('reason message'); $('button[name="open"]').attr('disabled', false); }; } function send() { var el = $('input[name="message"]'); var msg = el.val(); if (socket !== null && msg.length > 0) socket.send(encodeURIComponent(JSON.stringify({ message: msg }))); el.val(''); } function disconnect() { if (socket === null) return; $('button[name="close"],button[name="send"],button[name="rename"]').attr('disabled', true); $('button[name="open"]').attr('disabled', false); socket.close(); socket = null; } </script> 

This sounds like same-origin protections. 这听起来像同源保护。

Unless your socket.io server supports CORs and permits access from cross origin domains, the browser will not permit a connection to 127.0.0.1:8000 when the web page was loaded from localhost:8000 or vice versa. 除非您的socket.io服务器支持COR并允许从跨域访问,否则当从localhost:8000加载网页时,浏览器将不允许连接到127.0.0.1:8000 ,反之亦然。 The domain you are connecting to MUST match the domain of the web page unless your server supports CORS and explicitly allows cross origin connections. 您连接的域必须匹配网页的域,除非您的服务器支持CORS并明确允许跨源连接。

And, even though localhost:8000 and 127.0.0.1:8000 may actually be the same server, the browser will not allow it. 而且,即使localhost:8000127.0.0.1:8000实际上可能是同一台服务器,浏览器也不会允许它。

The usual way to solve your specific issue is to just use window.location from your Javascript to get the form of the host name that is in the current page URL and construct your URL with that host name so you make sure you are using the same host name in the page URL. 解决特定问题的通常方法是仅使用Javascript中的window.location获取当前页面URL中的主机名形式,并使用该主机名构造URL,以确保使用相同的主机名。页面URL中的主机名。

For example: 例如:

socket = new WebSocket('ws://' + window.location.host + '/');

I presume this goes without saying that your nginx proxy also has to be specifically configured to support webSocket connections. 我认为这不用说你的nginx代理也必须专门配置为支持webSocket连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM