http-party / node-http-proxy

A full-featured http proxy for node.js
https://github.com/http-party/node-http-proxy
Other
13.94k stars 1.98k forks source link

Express + http-proxy + websockets #891

Open that1guy opened 9 years ago

that1guy commented 9 years ago

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});
    });
andreabadesso commented 9 years ago

+1

kevinsimper commented 8 years ago

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

fullstackwebdev commented 8 years ago

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

MethodGrab commented 8 years ago

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.

shrihari-b commented 7 years ago

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

frow commented 6 years ago

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

ghost commented 2 years ago

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 + "/");
});