node-http-proxy icon indicating copy to clipboard operation
node-http-proxy copied to clipboard

Express + http-proxy + websockets

Open that1guy opened this issue 8 years ago • 7 comments

I'm trying to run a proxy server on port 8081 that can re-route http traffic and socket.io traffic. I'm using express server because I use passport for authentication.

I can get http-proxy to route all http traffic on 8081 and all websocket traffic directed to 8082, but I cant figure out how to handle both protocols on one port. Ideas?

This first technique just causes client-side xhr requests to hit the server at a rate of about 3 requests per second.

var express  = require('express');
var app      = express();

var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var bodyParser   = require('body-parser');

//Enable Gzip
app.use(compress());


    var postingAPI = 'http://localhost:4043',
        realtimeAPI = 'ws://localhost:4044',
        notificationAPI = 'http://localhost:4444';

    app.all("/v1/postings/*", function(req, res) {
        console.log('redirecting to posting api');
        apiProxy.web(req, res, {target: postingAPI});
    });

    app.all("/v1/queues/*", function(req, res) {
        console.log('redirecting to notification api');
        apiProxy.web(req, res, {target: notificationAPI});
    });


    app.on('connection', function (req, socket, head) {
        apiProxy.ws(req, socket, head, {
            target: realtimeAPI
        });
    });

    app.on('join-room', function (req, socket, head) {
        apiProxy.ws(req, socket, head, {
            target: realtimeAPI
        });
    });

app.use(bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({
    extended: true
}));


// start Node server ===========================================================
app.listen(8081);

This second method catches the websocket request, but obviously doesn't get upgraded.

var express  = require('express');
var app      = express();

var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var bodyParser   = require('body-parser');

//Enable Gzip
app.use(compress());


    var postingAPI = 'http://localhost:4043',
        realtimeAPI = 'ws://localhost:4044',
        notificationAPI = 'http://localhost:4444';

    app.all("/v1/postings/*", function(req, res) {
        console.log('redirecting to posting api');
        apiProxy.web(req, res, {target: postingAPI});
    });

    app.all("/v1/queues/*", function(req, res) {
        console.log('redirecting to notification api');
        apiProxy.web(req, res, {target: notificationAPI});
    });

    app.all("/socket.io/*", function(req, res) {
        console.log('redirecting to realtime api');
        apiProxy.web(req, res, {target: realtimeAPI});
    });


app.use(bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({
    extended: true
}));


// start Node server ===========================================================
app.listen(8081);

ws

I've tried a 3rd method using .ws method but no luck there either.

    app.all("/socket.io/*", function(req, socket, head) {
        console.log('redirecting to realtime api');
        apiProxy.ws(req, socket, head, {target: realtimeAPI});
    });

that1guy avatar Oct 16 '15 22:10 that1guy

+1

andreabadesso avatar Nov 13 '15 02:11 andreabadesso

@that1guy Did you see the example in the readme, that listens on "upgrade"?

kevinsimper avatar Dec 19 '15 14:12 kevinsimper

did this get resolved? I'm having similar issues. Upgrade didn't catch the /socket.io request and thus was never reached.

fullstackwebdev avatar Jan 12 '16 02:01 fullstackwebdev

I was also having similar issues proxying socket.io connections, which I've now solved! Heres an example that might help: https://github.com/MethodGrab/socketio-proxy-boilerplate.

MethodGrab avatar Jan 14 '16 13:01 MethodGrab

Facing same issue. As a workaround I removed express.It works fine after that.

shrihari-b avatar May 17 '17 08:05 shrihari-b

I also faced the same issue, I'm using different express middlewares which should also run on websocket connection attempts and removing express was not an option.

I implemented proxying for websockets via manually proxying the messages - I've put together some proof-of-concept code here, happy if it helps anybody: https://gist.github.com/frow/eb0b649bce510587299741d34dc486c5

frow avatar Sep 07 '18 11:09 frow

I ended up wrapping the express instance in http.createServer.

Looks a bit like this:

import * as http from "http";
const server = http.createServer(app); // where app is the Express app
const httpProxy = require("http-proxy");
const proxy = httpProxy.createProxyServer({ target: "http://localhost:3001", ws: true });
app.use((req, res) => proxy.web(req, res));
server.on("upgrade", (req, socket, head) => {
  proxy.ws(req, socket, head);
});
server.listen(port, () => {
  console.log("Listening at http://localhost:" + port + "/");
});

ghost avatar Jul 08 '22 05:07 ghost