simon
simon

Reputation: 1980

nodejs node-proxy, use a route table and modify response

We have a simple nodejs process for testing/dev work in our lab. We are using node-proxy to set up a reverse proxy that allows us to communicate with a https server using http (i.e. http -> https). As part of this we have some code for modifying the response. Here is what we are doing:

var http = require('http'),
    httpProxy = require('http-proxy'), 
    endserver = 'server.local',
    endport = 8443;

var proxy = new httpProxy.HttpProxy({ 
  target: {
    https: true,
    host: endserver,
    port: endport
  } 
});

http.createServer(function (req, res) {
  //our code for modifying response is here...
  proxy.proxyRequest(req, res);
}).listen(8001);

I want to set up a node-proxy routing table, like this example here, so I can forward requests to different https servers depending on the hostname in the request (I will set up multiple host names on our dns pointing to the same server running the nodejs proxy).

How can I have a node-proxy routing table and modify the response?

(I am quite new to node.js but not to javascript)

Upvotes: 1

Views: 846

Answers (1)

Mack
Mack

Reputation: 2724

If I read your question correctly, you just need to know how to route requests for different hosts based on the request object using a node-proxy routing table. This is actually addressed by the node-http-proxy docs: Proxy requests using a ProxyTable

Pasting it over, you just need to configure paths in a JS object like this:

var options = {
  router: {
    'foo.com/baz': '127.0.0.1:8001',
    'foo.com/buz': '127.0.0.1:8002',
    'bar.com/buz': '127.0.0.1:8003'
  }
};

Then pass this object in when you make your proxy server:

var proxyServer = httpProxy.createServer(options);
proxyServer.listen(80);

Specifying this for your code results in something like this:

var http = require('http'),
    httpProxy = require('http-proxy'), 
    endserver = 'server.local',
    endport = 8443;

var options = {
  router: {
    endserver + '/foo': '127.0.0.1:8081',
    endserver + '/bar': '127.0.0.1:8082',
    endserver + '/baz': '127.0.0.1:8083'
  }
};

var proxyServer = httpProxy.createServer(options);
proxyServer.listen(endport);

http.createServer(function (req, res) {
  // your code for modifying response is here...
  proxy.proxyRequest(req, res);
}).listen(8001);

It's not necessary to set the target yourself when using the router option. It seems the https distinction is also handled, but I'm not sure on that. I got this info from the proxy-table.js source. In particular:

ProxyTable.prototype.setRoutes = function (router) {
  if (!router) {
    throw new Error('Cannot update ProxyTable routes without router.');
  }

  var self = this;
  this.router = router;

  if (this.hostnameOnly === false) {
    this.routes = [];

    Object.keys(router).forEach(function (path) {
      if (!/http[s]?/.test(router[path])) {
        router[path] = (self.target.https ? 'https://' : 'http://')
          + router[path];
      }

      var target = url.parse(router[path]),
          defaultPort = self.target.https ? 443 : 80;

      //
      // Setup a robust lookup table for the route:
      //
      // {
      // source: {
      // regexp: /^foo.com/i,
      // sref: 'foo.com',
      // url: {
      // protocol: 'http:',
      // slashes: true,
      // host: 'foo.com',
      // hostname: 'foo.com',
      // href: 'http://foo.com/',
      // pathname: '/',
      // path: '/'
      // }
      // },
      // {
      // target: {
      // sref: '127.0.0.1:8000/',
      // url: {
      // protocol: 'http:',
      // slashes: true,
      // host: '127.0.0.1:8000',
      // hostname: '127.0.0.1',
      // href: 'http://127.0.0.1:8000/',
      // pathname: '/',
      // path: '/'
      // }
      // },
      //
      self.routes.push({
        source: {
          regexp: new RegExp('^' + path, 'i'),
          sref: path,
          url: url.parse('http://' + path)
        },
        target: {
          sref: target.hostname + ':' + (target.port || defaultPort) + target.path,
          url: target
        }
      });
    });
  }
};

Upvotes: 2

Related Questions