在具有 Apache 反向代理的服务器上使用 Node.js 和 Socket.io

10

我正在尝试使用Node.js和Socket.IO来实现浏览器和客户端之间的消息传递,遵循指南

但是,我不得不在Apache后面设置反向代理的Node。因此,我使用example.com/nodejs/替代了node的example.com:8080。

这似乎导致Socket.IO失去了自己的意义。这是我的node应用程序:

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,但它没有返回预期的 JavaScript 内容,而是返回“欢迎使用 socket.io”,就像我访问http://example.com/nodejs/一样。有什么办法可以解决这个问题吗?

我知道这与手头的问题无关(如果我应该开一个新的SO问题,请指出),但我很好奇你的Apache httpd.conf是什么样子的。我已经设置了代理以便将请求传递给实际的node.js服务器,但是我无法让websockets代理工作。你能否举个例子说明你是如何使用Apache做到这一点的? - pmalbu
抱歉,无法进行此项操作。该项目是在两年前的黑客马拉松中完成的,并且用于它的服务器已经不存在了。 - Peter Bailey
3个回答

9
这最终成为了多管齐下的解决方案。
首先,在服务器端,我需要设置如下的端点。
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端口。


2
你使用的是哪个版本的socket.io?我尝试了提到的解决方案。但是,如果Web套接字请求通过Apache mod_proxy路由,则所有HTTP标头都会被删除。因此,socket.io将关闭连接并显示“websocket connection invalid”。 - Selvaraj M A

4
我不认为这与你的 Apache 代理有任何关系,而是与 socket.io 如何处理子目录请求的一些“怪癖”有关。请参见我的答案。NGINX 配置以与 Socket.IO 协同工作 基本上,你需要使用以下连接语句: var socket = io.connect('http://example.com', {resource:'nodejs/socket.io'});

3
自 Socket.IO 1.0 版本开始,{resource: ...} 被替换为 {path: ...} - ceremcem

0
如果有人感兴趣,只有这个对我有效。 将端口3000替换为您的Nodejs端口
在您的VirtualHost中使用Apache 2.2.14
    <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 方面不需要做任何更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接