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

Proxying websockets to multiple servers #1065

Open zacharynevin opened 8 years ago

zacharynevin commented 8 years ago

Hello,

I have 3 services and an "api gateway". One service accepts HTTP requests, and the other 2 are websocket services. I want to do URL-based routing to these services. For example:

When I do this, the websocket request never seems to reach the target server (no errors).

I have the following:

boot.js

global.proxy = new httpProxy.createProxyServer()
app.use(require('./routes')

const server = http.createServer(app)

server.on('upgrade', (req, socket, next) => {
  var url = req.url

  if (/^(\/route2)/.test(url)) {
    var upstream = upstreams.route2
  } else if (/^(\/route3)/.test(url)) {
    var upstream = upstreams.route3
  }

  proxy.ws(req, socket, head, {
    target: {
      host: upstream.host,
      port: upstream.port
    }
  })
})

routes.js

const express = require('express')
const router   = module.exports = express.Router()

router
  .use('/route1', (req, res) => {
    proxy.web(req, res, {
      target: `${upstreams.route1}`,
      changeOrigin: true
    })
  })
  .use('/route2', (req, res) => {
    proxy.web(req, res, {
      target: `${upstreams.route2}`,
      changeOrigin: true,
      ws: true
    })
  })
  .use('/route3', (req, res) => {
    proxy.web(req, res, {
      target: `${upstreams.route3}`,
      changeOrigin: true,
      ws: true
    })
  })
Craigzyc commented 7 years ago

Did you get anywhere with this? I'm having a hard time getting this to work with routed websockets as well

zacharynevin commented 7 years ago

I didn't get anywhere with it. Your best bet is to use nginx

Craigzyc commented 7 years ago

Even the basic example does not work for me. If i follow the example from the docs but add a console log to see it happen I get the upgrade event firing somewhere between 40-50 times for each connection. It then fails over and uses polling.

I'm actually trying to do authentication and use a mongo database lookup to redirect the requests to somewhere in the area of 30-40 (future 1000) possible targets. Since the targets are all cellular I also intercept requests for static files and server them from a local node instance. Its tough to accomplish any of that in nginx. It works perfectly with regular requests and was working with sockets using bouncy before.

I only came to http-proxy thinking it would help with ws:// requests which also don't work

Does anyone have an idea why the basic example does not work?

//
// Setup our server to proxy standard HTTP requests
//
var proxy = new httpProxy.createProxyServer({
  target: {
    host: 'localhost',
    port: 9015
  }
});
var proxyServer = http.createServer(function (req, res) {
  proxy.web(req, res);
});

//
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
proxyServer.on('upgrade', function (req, socket, head) {
  console.log('SOCKET REQUEST');    //THIS IS FIRED ABOUT 40-50 TIMES PER CONNECTION ATTEMPT.
  proxy.ws(req, socket, head);            //THIS LEADS TO EventEmitter memory leak detected
});

proxyServer.listen(8015);
patdaman commented 6 years ago

I see that you are missing ws: true in the proxy definition:

var proxy = httpProxy.createProxyServer({ target: { host: 'localhost', port: 9015 } ws: true });

That being said, I can't get it to work either...

CraigZych commented 6 years ago

It took me a lot of work to get a perfectly working system.

I couldn't use nginx as suggested since I needed authenticated routes and routes redirected based upon information stored in mongodb.

If you need some help i can look up what I did for the basic proxy part. Might have used a different library

patdaman commented 6 years ago

I actually used Typescript to create the proxy, and (annoyingly...) I started to output compiled files to a different directory at some point and wasn't running the right script. It seems to work now, although I'll hit you up when I get to the next hurdle. Thanks!!

bard commented 6 years ago

@CraigZych how did you get this to work?