Onboarding

Configure Nginx as a reverse proxy for your Express API

Chenosis
POSTED 4 months ago
What we are going to achieve
In this beginner tutorial we'll get you up and running with a very basic "What's the time?" Node.js API. We'll then configure an HTTP reverse proxy using Nginx to listen on the default HTTP/s ports and forward web traffic to our API running on a loopback address. Here goes!
What's an API
In the simplest form an Application Programming Interface allows one thing to exchange information with another thing. Essentially an API establishes how communication should happen and is responsible for handling that communication, or better yet handling the data transfer between two entities.

Ever visited a website contact page and seen an embedded Google map with a pin representing the business location... well you've been staring at an API (or the result of one) this whole time. Here the website owner has sent their physical address to the Google Maps API which in turn has done all of the crunching on the Google servers and returned the nice and simple code needed to display this map for you.
What's an HTTP Reverse Proxy
A reverse proxy is an intermediary service that sits between a client and another service. It is responsible for forwarding requests and responses between a client and a service. There are many reasons why you would want to utilise a reverse proxy, from load balancing to better security. Our primary purpose though is to access our API using a domain (mapped to port 80 for HTTP and 443 for HTTPS).
What's a loopback address
Heard of localhost or 127.0.0.1? We also know this as home but it's really called a loopback address. A loopback address is a special IP address that is not associated with a physical network card but is rather a software "interface" that server applications or services can use to communicate with one another. In this tutorial our API will be available from the loopback address http://localhost:3000 (this is also IP 127.0.0.1 and via port 3000).
Building the API
Alright, that's enough theory. It's time to get our hands dirty!

You'll need to have Node.js installed on your machine. You can confirm this by opening up your terminal and typing node -v. If you don't see a response with a version number you'll need to head on over to https://nodejs.org/ and follow the download and installation instructions.

$ node -v
v11.15.0
Now create a new file called server.js in your favourite editor and paste this code.

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send(new Date().toLocaleTimeString())
})

app.listen(port, () => {
  console.log(`Example app listening at 127.0.0.1:${port}`)
})
Lines 1 & 2:
We've started out by requiring a Node.js module called Express. Express is a "fast, unopinionated, minimalist web framework for Node.js". Whenever you require a Node.js module you must first install it. We can use the built in Node Package Manager (npm) to do this. Go ahead and do this now.

npm i express
Line 3:
Here we tell our API to listen on port 3000 (via the loopback address)

Lines 5 - 7:
Listen for a GET HTTP request on the root route and return the current server time

Lines 9 - 11:
Start listening on the defined port (3000) and print a message to the console so we know everything is up and running

That's it, our API is ready! I did warn you that it was basic. Go ahead and fire it up and then visit http://127.0.0.1:3000 in your browser.

$ node server.js
Example app listening at 127.0.0.1:3000
Screenshot 2021-04-29 at 21.37.21.png 75.13 KB

Remember that 127.0.0.1:3000 is a local address, so handing it out to your friends and family won't work. They'll need your servers static external IP address which you can get by entering the following in the terminal.

$ dig +short myip.opendns.com @resolver1.opendns.com
169.xxx.xxx.xxx
They could now use http://169.xxx.xxx.xxx:3000 to access your API, but handing out IP addresses and ports are not a good idea so we should rather use a reverse proxy to map a domain name to our new service.
Configuring the HTTP reverse proxy
This tutorial is going to assume that you already have Nginx installed on your server and that you've purchased a domain name and updated the DNS records to point to your server's IP address. If you need some help with this you can review this great article on Digital Ocean.

Start by navigating to the Server Block (Virtual Host) directory and disable the default configuration

$ cd /etc/nginx/sites-enabled/
$ ls
default

$ unlink /etc/nginx/sites-enabled/default
Now create a new reverse-proxy.conf file in /etc/nginx/sites-available/

$ cd /etc/nginx/sites-available/
$ nano reverse-proxy.conf
and add the following configuration...

server {
    listen 80;
    server_name  yourdomain.com;

    access_log /var/log/nginx/reverse-access.log;
    error_log /var/log/nginx/reverse-error.log;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}
Line 2 & 3:
Tells the proxy to listen on port 80 (HTTP) for the domain yourdomain.com. This is equivalent to http://yourdomain.com in the browser. Notice now that we aren't defining the port as browsers know to map http:// to port 80 and https:// to port 443.

Lines 5 & 6:
We're telling Nginx where to write the logs for this reverse proxy.

Lines 8-10:
This is where the magic is happening, we're passing the traffic from port 80 to our internal loopback address at port 3000.

Go ahead and enable the new configuration by "adding" it to /etc/nginx/sites-enabled/

$ ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/reverse-proxy.conf
Test your configuration file before restarting the Nginx service

$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

$ sudo service nginx restart
Screenshot 2021-04-29 at 21.44.35.png 22.64 KB
If all went well you (and your friends) can now access your API from http://yourdomain.com

Next steps
I hope this has helped your understanding and that you're at least slightly proud of what you have achieved... but don't stop here.

Take this to next level by:

  1. Installing an SSL certificate on your server
  2. Configuring your reverse proxy to use port 443 (HTTPS)
  3. Configuring your reverse proxy to forward all traffic from port 80 to port 443
  4. Protecting your reverse proxy with basic HTTP authentication
  5. Building an API that handles multiple HTTP methods like GET, PUT, POST & PATCH
  6. Connect your API to another API Product on the Chenosis Marketplace