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.

Другие вопросы по тегам