8
votes

I'm trying to build a proxy server on with Node.js on Heroku using http-proxy. Everything works fine locally, but I'm having some troubles on Heroku.

var http = require('http');
var httpProxy = require('http-proxy');

settings = {
  "localhost": process.env.LOCALHOST,
  "devices":   process.env.DEVICES_URI
}

var options = { router: { } }
options.router[settings.localhost + '/devices']  = settings.devices + '/devices';

var port   = process.env.PORT || 8000;
var server = httpProxy.createServer(options).listen(port);

As you can see the in the example I set a routing object. What I say is this: when a request matches '/devices' then route the request to the the device service. (identified by the DEVICES_URI environmental var)

In development I set

  • LOCALHOST = 'localhost'
  • DEVICES_URI = 'http://localhost:3000'

This means that all requests going to localhost:8000/devices are proxied to localhost:3000/devices which is what I want. All works perfectly.

The problem is in production. It gives me a timeout error repeated multiple times for every request.

2012-08-23T20:18:20+00:00 heroku[router]: Error H12 (Request timeout) -> GET lelylan-api.herokuapp.com/devices dyno=web.1 queue= wait= service=30000ms status=503 bytes=0

In the production the environment vars are configured to the app names.

  • LOCALHOST = 'lelylan-api.herokuapp.com'
  • DEVICES_URI = 'lelylan-devices.herokuapp.com/'

I guess I'm wrong is some configurations, but after the whole day I'm still not able to figure it out.

Update

I've continued with my tests and I've seen that the proxy is not able to reach the proxied service which totally stops me.

In development I set:

  • LOCALHOST = 'localhost'
  • DEVICES_URI = 'lelylan-devices.herokuapp.com/'

If I call http://lelylan-devices.herokuapp.com/devices everything works fine.

If I call localhost:8000/devices (which points to http://lelylan-devices.herokuapp.com/devices) Heroku tells me there is no such an app. I guess the problem is somehow in the routing system.

Here you can access at the source code. Here the configuration vars for Heroku.

NODE_ENV      => production
LOCALHOST     => lelylan-api.herokuapp.com
DEVICES_URI   => lelylan-devices.herokuapp.com
TYPES_URI     => lelylan-types.herokuapp.com
LOCATIONS_URI => lelylan-locations.herokuapp.com
2
Is the , in your settings object in the correct place?Mike M
Typo on simplifying the code for the post. You can see the complete file here (a bit messy, but i'm in full development).Andrea Reginato

2 Answers

5
votes

I finally made it work using a slightly modified version proxy-by-url. The final code looks something like this and works fine.

var httpProxy = require('http-proxy');

var port = process.env.PORT || 8000;

var routing = {
  '/devices': { port: process.env.DEVICES_PORT || 80, host: process.env.DEVICES_URI }
}

var server = httpProxy.createServer(
  require('./lib/uri-middleware')(routing)
).listen(port);

One note to remember. The plugin sets the header HOST to the destination application uri. If you do not do so, Heroku will not recognize the app and will not find it, as its internal routing system seems to be based on the HOST header.

2
votes

I use http-proxy successfully on Heroku. The first thing I noticed in your log err is the url it is GETting: GET lelylan-api.herokuapp.com/tdevices

There is a typo... instead of '/devices' it shows '/tdevices'. Before continuing can you confirm this is the actual log message?