Использование socket.io с nodejs на сервере с apache в качестве обратного прокси

Я пытаюсь использовать Node.js с Socket.IO для облегчения обмена сообщениями между браузером и клиентом, следуя руководство.

Однако мне пришлось настроить обратное проксирование Node за Apache. Итак, вместо example.com:8080 для узла я использую example.com/nodejs/.

Кажется, это приводит к тому, что Socket.IO теряет смысл. Вот мое приложение узла

var io = require('socket.io').listen(8080);

// this has to be here, otherwise the client tries to 
// send events to example.com/socket.io instead of example.com/nodejs/socket.io
io.set( 'resource', '/nodejs/socket.io' );

io.sockets.on('connection', function (socket) {

  socket.emit('bar', { one: '1'});

  socket.on('foo', function( data )
  {
    console.log( data );
  });

});

А вот как выглядит мой клиентский файл

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Socket.IO test</title>

  <script src="http://example.com/nodejs/socket.io/socket.io.js"></script>

  <script>

  var socket = io.connect('http://example.com/nodejs/');

  console.log( socket );

  socket.on( 'bar', function (data)
  {
    console.log(data);
    socket.emit( 'foo', {bar:'baz'} );
  });

  socket.emit('foo',{bar:'baz'});

  </script>
</head>
<body>
  <p id="hello">Hello World</p>
</body>
</html>

Проблема здесь в том, что скрипт ссылается на http://example.com/nodejs/socket.io/socket.io.js. Он не возвращает ожидаемый контент javasscript — вместо этого он возвращает «Добро пожаловать в socket.io», как если бы я нажал http://example.com/nodejs/.

Любая идея, как я могу сделать эту работу?


person Peter Bailey    schedule 03.05.2012    source источник
comment
Я знаю, что это не связано с рассматриваемым вопросом (и, пожалуйста, позвоните мне, если я должен открыть новый вопрос SO), но мне любопытно, как выглядит ваш Apache httpd.conf. У меня настроен прокси для передачи на фактический сервер node.js, однако я не могу заставить работать прокси-сервер websockets. Не могли бы вы привести пример того, как вы делаете это с Apache?   -  person pmalbu    schedule 15.08.2014
comment
Извини, но я не могу. Этот проект был сделан на хакатоне более 2 лет назад, и сервер, который был настроен для него, больше не существует.   -  person Peter Bailey    schedule 15.08.2014


Ответы (3)


Это оказалось многоцелевым решением.

Во-первых, на стороне сервера мне пришлось настроить конечные точки следующим образом.

var io = require('socket.io').listen(8080);

var rootSockets = io.of('/nodejs').on('connection', function(socket)
{
  // stuff
});

var otherSockets = io.of('nodejs/other').on('connection', function(socket)
{
  // stuff
});

Затем на стороне клиента правильное подключение выглядит так

var socket = io.connect(
    'http://example.com/nodejs/'
  , {resource: 'nodejs/socket.io'}
);

// The usage of .of() is important
socket.of('/nodejs').on( 'event', function(){} );
socket.of('/nodejs/other').on( 'event', function(){} );

После этого все заработало. Помните, что на этом сервере Apache использует проксирование example.com/nodejs для внутреннего порта 8080.

person Peter Bailey    schedule 09.05.2012
comment
Какую версию socket.io вы использовали? Я попробовал упомянутое решение. Но все заголовки http удаляются, если запрос веб-сокета направляется через apache mod_proxy. Итак, socket.io закрывает соединение, поскольку соединение с веб-сокетом недействительно. - person Selvaraj M A; 24.04.2013

Я не думаю, что это имеет какое-то отношение к вашему прокси-серверу apache, но некоторые «причуды» связаны с тем, как socket.io обрабатывает запросы в подкаталоге. Смотрите мой ответ здесь. Конфигурация NGINX для работы с Socket.IO

По сути, вместо этого вам нужно использовать этот оператор подключения:

var socket = io.connect('http://example.com', {resource:'nodejs/socket.io'});

person Timothy Strimple    schedule 04.05.2012
comment
Начиная с socket.io 1.0 {resource: ... заменяется на {path: ... - person ceremcem; 17.11.2014

Если кому интересно, только это сработало для меня. Замените порт 3000 на свой порт Nodejs

Apache 2.2.14 внутри вашего VirtualHost

    <IfModule mod_proxy.c>
      <Proxy *>
        Order allow,deny
        allow from all
      </Proxy>
    </IfModule>

    RewriteEngine on

    RewriteCond %{QUERY_STRING} transport=polling
    RewriteRule /(.*)$ http://localhost:3001/$1 [P]

    ProxyRequests off
    ProxyPass /socket.io/ ws://localhost:3001/socket.io/
    ProxyPassReverse /socket.io/ ws://localhost:3001/socket.io/

Подключение на стороне клиента:

  var myIoSocket = io.connect($location.protocol() + '://' + $location.host(), {path: '/socket.io'});

Не нужно ничего менять на стороне Node.js.

person Ulterior    schedule 21.04.2016