Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proxy server with Node.js on Heroku

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
like image 453
Andrea Reginato Avatar asked Aug 23 '12 16:08

Andrea Reginato


People also ask

Does Heroku use proxy?

By default, heroku-proxy will proxy all requests to /api/* of any method to api.heroku.com via https . You can override the default options by passing an object into the function returned by the heroku-proxy module: app.

How do I host a Heroku proxy?

Follow these simple steps to create a proxy server on Heroku: Step 1: Setting up a local repository. Clone your remote repository to the local directory. Now cd into your cloned repository and run the command npm install to install all node dependencies into your project.

Does Heroku support node JS?

Initially, it supported only Ruby sites but now supports various languages, including JavaScript with Node. js. Heroku also has Docker support so that you can deploy just about anything to it. This tutorial will teach you how to build a small application using the Express framework for Node.


1 Answers

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.

like image 140
Andrea Reginato Avatar answered Oct 01 '22 19:10

Andrea Reginato