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.
Summary. While the HTML5 Web Socket protocol itself is unaware of proxy servers and firewalls, it features an HTTP-compatible handshake so that HTTP servers can share their default HTTP and HTTPS ports (80 and 443) with a WebSocket server.
The theoretical limit is 65k connections per IP address but the actual limit is often more like 20k, so we use multiple addresses to connect 20k to each (50 * 20k = 1 mil).
Node. js can maintain many hundreds of WebSockets connections simultaneously. WebSockets on the server can become complicated as the connection upgrade from HTTP to WebSockets requires handling. This is why developers commonly use a library to manage this for them.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With