“Person holding a plastic coffee cup in front of colorful wall at Venice Beach” by Marion Michele on Unsplash

Hosting multiple apps on the same server — Implement a reverse proxy with Node

David Mellul
ITNEXT
Published in
5 min readMay 1, 2018

--

Whenever I choose a new cloud-hosting plan in order to have a remote server for my developments, I’m often to run multiple apps on it.

There are many reasons to this, for instance:

  • It allows me to keep my computer clean from the garbage that comes with downloading and installing tons of IDEs, libraries, packages, etc.
  • It allows me to have a server running 24/7 so that my customers can follow my progression whenever they want.
  • It removes the hassle of configuring my box to allow public visitors on my projects.
  • Basically a physical server is a computer just like any other, so why would I host only 1 app per server ?

Now comes the implementation part, and if you’ve tried yourself at this exercise you know that it often ends like this :

Multiple projects, each one is running on a specific port

What has to be noticed here is that once you’re running a project, it listens on a specific port and you have to keep a list of which ports are used if you don’t want to stumble across a fatal error :

EADDRINUSE: This port is already in use

The other pain point is that when you’re interacting with your program, your requests will look something like this :

http(s)://domain.ext:port/route

With port being the port your project listens on.

The goal of this article is to teach you how to create a reverse proxy so that in the end you’ll be able to use meaningful urls for your projects.

Just like that:

http(s)://domain.ext/nameOfYourProject/route

Instead of having to remember which port your app is listening on.

First, what is a reverse proxy ?

A picture is worth thousand words.

Credits to myself 😆

In brief, a reverse proxy will match incoming requests with their component.

It’s just a request organizer. Its role is to redirect requests based on criteria (URL parts, request body, basically anything can be a criterion) and to give the response back from the component the request has been redirected to.

In this example, the reverse proxy running on port 443 will proxy REST requests to the Python REST API listening on port 5000 and it will proxy website requests to the Apache server listening on port 80.

For this particular case (a real use-case I dealt with), the criterion was the URL part after the domain name, like this :

https://website.com/rest -> Python REST API

https://website.com/web -> Apache web server

How to implement one ?

Before we start, make sure that you have the following :

  • Node : https://nodejs.org/en/
  • Express : npm install express
  • HTTP Proxy Middleware : npm install http-proxy-middleware

Express will allow you to run a server, and HTTP Proxy Middleware will proxy requests to the endpoints you configured.

Finally, we’ll use a JSON config file which will contain a mapping like this :

It means that once /project1 is requested, the request is proxied to http://localhost:1001 .

Assuming you created a JSON file and a JS file to run a server, this is what you should end with:

/project
app.js
config.json

And this is the code you have to insert into app.js :

The explanation is:

  • Line 6 : Turning the JSON file into a JS object via require
  • Line 10 : Iterating over all the routes, one by one
  • Line 11 : Using app.use(route,handler) means that no matter the HTTP method used in the requests, the server will use handler when route is requested.
  • Line 12 : Create an anonymous handler which will proxy requests (documentation here)
  • Line 13 : The target is where the request will be sent to
  • Line 14 : pathRewrite can be a function. We defined ours so that it strips the sugar part. Let me explain.

To access project1 , you will open your browser and type: http://domain.ext/project1/route/parameters/blabla

When called, pathRewrite will fill the path parameter with what comes juste after the domain part.

In our case, path will be equal to : /project1/route/parameters/blabla

But in fact, your app only needs what comes after /project1 .

That’s how you get rid of it :

  • path.split('/') =['','project1','route','parameters','blabla']
  • .slice(2) = ['route','parameters','blabla']
  • .join('/') = route/parameters/blabla (the leading / before route isn’t necessary)
  • Line 21 : Run the server and you’re good to go 😃

I recommend running your reverse proxy daemonized with a crash-proof launcher like pm2 or any other utility so that if it breaks it will restart automatically without compromising the projects it redirects to.

For instance :

pm2 start app.js

You should now be able to use meaningful URLs to access your different projects on the same server, without having to specify the port manually for each request.

Note that this reverse proxy would also work using https (that’s what I’m personally up to).

Author’s note

This article brings a useful trick I often use in my daily developer life.

You could be thinking “well, I don’t have to type the port anymore but I still have to type a keyword”. Which one is more meaningful to you ?

Like always, you’re free to make your choices.

Thanks for reading

My last article is available here : Node + Express + LetsEncrypt : Generate a free SSL certificate and run an HTTPS server in 5 minutes or less

I appreciate comments, suggestions and debates.

Feel free to reach out at david.mellul@outlook.fr 😃 ☕️

“Cappuccino in a white mug with white foam art on a wooden table” by wu yi on Unsplash

--

--