简体   繁体   中英

Using socket.io with nodejs on a server with apache as a reverse proxy

I'm attempting to use Node.js with Socket.IO to faciliate messaging between the browser and client, following the guide .

However, I had to setup Node reverse-proxied behind Apache. So, instead of example.com:8080 for node, I'm using example.com/nodejs/.

This seems to cause Socket.IO to lose sense of itself. Here's my node app

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 );
  });

});

And here's what my client file looks like

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

The problem here is the script reference to http://example.com/nodejs/socket.io/socket.io.js . It doesn't return the expected javasscript content - instead it returns "Welcome to socket.io" as if I hit http://example.com/nodejs/ .

Any idea how I can make this work?

This ended up being a multi-pronged solutions.

First, on the server end of things, I had to set up the endpoints like this

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
});

Then, on the client-side, to properly connect looks like this

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(){} );

After this, it all worked. Remember, on this server Apache is proxying example.com/nodejs to port 8080 internally.

I don't think this has anything to do with your apache proxy, but some 'quirks' with how socket.io handles requests on a sub-directory. See my answer here. NGINX configuration to work with Socket.IO

Basically, you need to use this connect statement instead:

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

If anybody is interested, only this worked for me. Replace port 3000 with your Nodejs port

Apache 2.2.14 inside your 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/

Client side connection:

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

No need to change anything on Node.js side.

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