Source Allies Logo

Sharing Our Passion for Technology

& Continuous Learning

<   Back to Blog

Node Reference - Koa

Teammates sitting together and looking at code

Prerequisites

This article builds on the prior article: Unit Testing.

Shift Left DevOps

Before we write code, we look at first principles. A key principle is: "shorten feedback loops". We can acheive this by automating the steps leading up to validating what we're building. This is one reason we focus on continuous integration and continuous deployment tasks at the very beginning of a new project. Leaders in our industry are doing the same with both security concerns and infrastructure as code / DevOps concerns - shifting these activities to the left or to beginning steps.

Therefore, our first order of business is to deploy an extremely small piece of software, what we call a "Canary Deployment". (Similar to a Canary Release{:target="_blank"}, a first prod release solves the same basic problem of avoiding a high-risk big-bang event). A Canary Deployment is an initial version of the application that lacks business functionality but can be deployed all the way to production in order to test the build process, deployment pipeline, access, security setup and monitoring. By focusing on these technical tasks before building functionality, troubleshooting build and deployment issues when they arrive will be simpler. It also removes the need to "fit in" these best practices later in the project. As with most things in software development, the longer you wait, the more it costs.

Hello Koa

While we could create an HTTP server using the raw NodeJS APIs, like most languages, it is much easier to use a library that will handle request routing and other low lever HTTP concerns for us. For this purpose I have chosen Koa. I started by looking at Express which was one of the first such libraries to gain popularity and is still probably the most popular as measured by downloads. However, in order to make unit testing simpler and handler methods easier to read, I wanted a library that would allow me to return a Promise so that I could leverage async/await rather than callbacks. HAPI is also another good option. Run the following command to install Koa and save it into your package.json file.

npm install --save koa koa-bodyparser

First, we will test drive a "handler" or module that responds to HTTP requests. We need to install the proxyquire library in order to help mock our dependencies. Run the following command to install proxyquire and save it to your package.json file.

npm install --save-dev proxyquire

Replace the contents of hello.spec.js that was created in the previous post with this content:

const proxyquire = require('proxyquire');

describe('hello handler', function() {
    beforeEach(function() {
        this.context = {};
        this.hello = proxyquire('./hello', {});
    });

    it('should respond with a 200 status', async function() {
        await this.hello(this.context);
        expect(this.context.status).toEqual(200);
    });

    it('should responsd with a hello message', async function() {
        await this.hello(this.context);
        expect(this.context.body).toEqual({message: 'hello'});
    });
});

Now we can create an implementation of this super simple handler in hello.js:

module.exports = async function hello(ctx) {
    ctx.status = 200;
    ctx.body = {
        message: 'hello'
    };
};

Next, create a file called server.js with the following content:

const Koa = require('koa');

const app = new Koa();

app.use(require('./hello')); //this is the handler we just created
app.listen(3000);

If we set the "start script" in package.json as follow, we can start the server with npm start:

{
    "scripts": {
        "start": "node server.js"
    }
    ...
}

Start the server with either npm start or node server.js and make an HTTP request to http://localhost:3000{:target="_blank"} and you should see some text back. We now have a working HTTP server.

Next we need to add some sort of request routing to decouple HTTP handlers from each other. Koa uses the practice of having several small, separate npm packages for different purposes so that only needed functionality is installed. For routing, install the koa-router{:target="_blank"} package.

npm install --save koa-router

Now modify server.js to use the koa-router package:

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const Router = require('koa-router');

const app = new Koa();

app.use(bodyParser());
app.use(buildRouter().routes());
app.listen(3000);

function buildRouter() {
    const router = new Router();
    router.get('/hello', require('./hello'));
    return router;
}

We can add additional routes to this file as needed. It provides an easy one-stop-shop for future developers to find out what code is executing for a given URL.

Congratulations, we now have a very simple NodeJS API running locally! You should be able to make a request to http://localhost:3000/hello{:target="_blank"} and see the JSON response. Remember to commit your changes. Follow along with our changes

Wrap-Up

Because of our goal to shift left the DevOps aspect of our microservice, we decided to first deploy a super small service. This article established that small service that we will deploy during the course of the next few articles in the series.

The next article will containerize the service to make it ready to deploy to the AWS platform.

Table of Contents

If you have questions or feedback on this series, contact the authors at nodereference@sourceallies.com.