Question

I have an application that uses websockets via socket.io. For my application I would like to use a separate HTTP server for serving the static content and JavaScript for my application. Therefore, I need to put a proxy in place.

I am using node-http-proxy. As a starting point I have my websockets app running on port 8081. I am using the following code to re-direct socket.io communications to this standalone server, while using express to serve the static content:

var http = require('http'),
    httpProxy = require('http-proxy'),
    express = require('express');

// create a server
var app = express();
var proxy = httpProxy.createProxyServer({ ws: true });

// proxy HTTP GET / POST
app.get('/socket.io/*', function(req, res) {
  console.log("proxying GET request", req.url);
  proxy.web(req, res, { target: 'http://localhost:8081'});
});
app.post('/socket.io/*', function(req, res) {
  console.log("proxying POST request", req.url);
  proxy.web(req, res, { target: 'http://localhost:8081'});
});

// Proxy websockets
app.on('upgrade', function (req, socket, head) {
  console.log("proxying upgrade request", req.url);
  proxy.ws(req, socket, head);
});

// serve static content
app.use('/', express.static(__dirname + "/public"));

app.listen(8080);

The above application works just fine, however, I can see that socket.io is no longer using websockets, it is instead falling back to XHR polling.

I can confirm that by looking at the logs from the proxy code:

proxying GET request /socket.io/1/?t=1391781619101
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294
proxying POST request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=1391781629
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294

Does anyone know how to proxy the web sockets communication? All the examples from node-http-proxy assume that you want to proxy all traffic, rather than proxying some and serving others.

Was it helpful?

Solution

Just stumbled upon your question, and I see that it is still not answered. Well, in case you are still looking for the solution... The problem in your code is that app.listen(8080) is just syntactic sugar for

require('http').createServer(app).listen(8080)

while app itself is just a handler function, not an instance of httpServer (I personally believe that this feature should be removed from Express to avoid confusion). Thus, your app.on('upgrade') is actually never used. You should instead write

var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) {
  proxy.ws(req, socket, head);
});
server.listen(8080);

Hope, that helps.

OTHER TIPS

Do you need both servers? If not you could use the same server for static files and to listen for socket connections:

// make the http server
var express = require('express'),
    app = express(), server = require('http').createServer(app),
    io;

// serve static content
server.use('/', express.static(__dirname + '/public'));

server.listen(8080);

// listen for socket connections
io = require('socket.io').listen(server);

// socket stuff here
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top