Node.js - Websocket отказывается открывать соединение, когда обслуживается обратным прокси-сервером Nginx.
В настоящее время я пытаюсь настроить простое приложение для чата. Я использую каркас total.js. Моя программа Node.js работает на [http]://127.0.0.1:8000/. Это работает до тех пор, пока URI запроса совпадает с точным URI, указанным в HTML-коде загруженной страницы. Например, перейдя по адресу [http]: // localhost: 8000 /, вы загрузите html-страницу, но все функции не будут работать, пока [http]: //127.0.0.1: 8000 будет работать как положено.
Я узнал об этом, пытаясь настроить Nginx в качестве обратного прокси-сервера, чтобы получить доступ к нему, перейдя по адресу [http]://127.0.0.1:80/. Здесь HTML-страница будет загружаться, но функциональность чата не будет работать.
Это приложение для чата является частью примеров total.js.
Вот файл 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>
1 ответ
Это звучит как защита того же происхождения.
Если ваш сервер socket.io не поддерживает COR и не разрешает доступ из доменов разных источников, браузер не разрешит подключение к 127.0.0.1:8000
когда веб-страница была загружена с localhost:8000
или наоборот. Домен, к которому вы подключаетесь, ДОЛЖЕН совпадать с доменом веб-страницы, если только ваш сервер не поддерживает CORS и явно не разрешает соединения между источниками.
И хотя localhost:8000
а также 127.0.0.1:8000
на самом деле может быть один и тот же сервер, браузер не позволит этого.
Обычный способ решить вашу конкретную проблему - просто использовать window.location
из вашего Javascript, чтобы получить форму имени хоста в URL текущей страницы и создать свой URL с этим именем хоста, чтобы убедиться, что вы используете то же имя хоста в URL страницы.
Например:
socket = new WebSocket('ws://' + window.location.host + '/');
Я предполагаю, что это само собой разумеется, что ваш прокси-сервер nginx также должен быть специально настроен для поддержки соединений webSocket.