简体   繁体   中英

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. My Node.js program runs on [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. 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.

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/. Here the html page would load, but the chat functionality woudn't work.

This chat app is part of the total.js examples.

Here is the index.html file which creates the websocket:

 <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. 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.

And, even though localhost:8000 and 127.0.0.1:8000 may actually be the same server, the browser will not allow it.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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