Build a REST API with Node.js, FRP, and Docker

REST APIs are all the rage these days. Since I'm a developer, I decided to create a vanity API using modern technology. What's a vanity API? An API about me, of course! This article is the first in a series in which I progressively explain my process of creating an API which allows you to interact with me as a freelance software developer.

REST

REST stands for Representational State Transfer and is loosely defined, but essentially refers to an architectural style based on using HTTP as a communication protocol. It has become popular because we've all become comfortable with HTTP as it has embedded itself into our lives and it's relatively simple. There is an effort to formalize it further with the JSON API.

Documentation

In order for the API to be valuable it must be easy to discover and to understand by developers. New tools have sprung up to support this need and for my API I've chosen to use Apiary to document it. Apiary even provides simple mocking, which I'll use as the implementation for this first iteration.

Monitoring

I'm a big fan of writing automated tests, including the method of Test Driven Development. My API will be a continuously available service, however, so I want to go beyond TDD. I want more than only the assurance that the code works properly once, as TDD gives me when I run the tests; I want assurance that the code is working constantly over time. To achieve this I need to go beyond what we normally call testing into what we call monitoring.

So I'm inventing a new acronynm: MDD, or Monitor Driven Development. That's right folks, you heard it here almost first (I see only a few hits on Google today for this phrase).

Minimal Viable Product

So what should I monitor in the first iteration of my vanity API? As little as possible, of course. The less I build, the faster it can be delivered to customers, and the more quickly it can be assessed as providing value or not. So for the first iteration of my API I define a single endpoint to monitor which returns my name:

Request

GET /name/

Response

200
Content-Type: application/json
"David Braun"

Functional Reactive Programming

The mechanics of an Internet API involve a lot of asynchronous events, such as HTTP requests and HTTP responses. In fact we could say that it involves a stream of such events, for example: a consumer request for a list of my open source projects would trigger another request to the GitHub API, then a response from GitHub, and finally a response to the original consumer. Any time we see a stream of asynchronous events we should consider using Functional Reactive Programming to model them. There are many libraries for doing this and for this project I decided to use Highland because it uses the standard Node.js stream interface.

Alerting

We don't monitor just for monitoring's sakeā€”it should have a purpose. The purpose of this monitor will be to alert me if the API stops working in order to minimize the mean time to recovery. A simple and convenient alerting service is Dead Man's Snitch. It will send an alert email to me if it doesn't receive an "All's well" report at least once per day.

Code

Now we have all the pieces in place to write the monitoring code:

'use strict';

var  
  _ = require('highland'),
  request = _.wrapCallback(require('request'));

// Test the name endpoint once per day.
_(function (push, next) {  
  push(null, 'http://private-9013f4-nodeguy.apiary-mock.com/name');
  setTimeout(next, 24 * 60 * 60 * 1000);
})
  .flatMap(request)
  .pluck('body')
  .map(JSON.parse)
  .filter(function (data) {
    return data === "David Braun";
  })
  .map('https://nosnch.in/0b09461076')
  .flatMap(request)
  .pluck('body')
  .pipe(process.stdout);

Here's a translation in English:

  1. Create a stream.
  2. Generate the URL of the name endpoint every 24 hours.
  3. Request my name from the API (the request returns a stream, so flatten it into a value).
  4. Isolate the body property of the response.
  5. Parse its JSON representation.
  6. Filter out any responses which don't correctly return my name.
  7. Change the response value to the URL for Dead Man's Snitch (it's not the real URL).
  8. Alert Dead Man's Snitch that we received a correct response today.
  9. Display their response body to stdout for debugging. This serves two functions: it both consumes the stream and provides some diagnostic information which is helpful while writing the code.

Big Red Light

Bonus feature: Build a Website Down Alarm with a Tessel (oh how I want but don't need one of these!).

big alarm light connected to Tessel

Delivery

Not long after I started my software engineering career, the CD-ROM was the standard software delivery vehicle. Today I argue it's a Docker container.

Docker has created a standard Node.js base, so our Dockerfile contains only one line:

FROM node:0.10-onbuild

Deployment

Where to deploy the Docker container? There isn't a great Docker container hosting service yet, though industry giants like Amazon and Google are racing to build one.

I like to do development with a remote Docker daemon running on DigitalOcean. For deployment I wouldn't want a reckless (but satisfying) docker kill $(docker ps -q) command to interfere with my services, so I run them in Tutum with the Autorestart flag set.

Icon?

It would be cool to put a badge on my website to advertise the API's existence, but so far I haven't seen a standard icon in use for this. Perhaps it's time to start a new trend. How about the cog icon in Font Awesome? Please share your ideas in the comments below.

View or Post Comments