The forever hap’i’ server – Part 1

A rich framework for building applications and services. Hapi.js is a robust configuration-centric framework that enables us to build REST APIs easily without having to go through lot of pain-points of infrastructure.

What does Hapi provide?

  • Built-in support for input validation
  • Caching
  • Authentication
  • Configuration-centric Server

The idea of this blog post and the couple of blog posts that are to follow is to convey how easy it is to create REST services using Hapi. We will create REST APIs for simple CRUD operations.

So, let’s get started with the installation of Hapi.js.

Getting Started

It’s fairly simple to install hapi.js on your machine. The only prerequisite for this is the presence of Node JS. While I write this post, I’m using Node Version 5.4.1.

Bootstrapping the application is the same as we bootstrap any node application.

We’ll initialize the application’s package.json file either manually or using the npm init command.

The Hapi.js documentation states:

Create a new directory myproject, and from there:

  • Run: npm init and follow the prompts, this will generate a package.json file for you.
  • Run: npm install --save hapi this installs hapi, and saves it in your package.json as a dependency of your project.
Creating Server
'use strict';

const Hapi = require('hapi');

const server = new Hapi.Server();
server.connection({ port: 3000 });

server.start(() => {
    console.log('Server running at:', server.info.uri);
});

This creates a simple Hapi server, which is running at the port 3000. For more configuration options, please refer to http://hapijs.com/api/#serverconnectionoptions

Adding routes

Now, we’ll add a simple route to check how addition of a route works.

'use strict';

const Hapi = require('hapi');

const server = new Hapi.Server();
server.connection({ port: 3000 });

server.route({
    method: 'GET',
    path: '/awesome',
    handler: function (request, reply) {
        reply('Im awesome!');
    }
});

server.start(() => {
    console.log('Server running at:', server.info.uri);
});

This creates a simple GET API http://localhost:3000/awesome which returns “Im awesome!”. We also notice that the content type header is set correctly without explicitly being set. This is one of the advantages of using Hapi.js

Building the APIs

Now, moving forward, with this knowledge, let’s create simple REST APIs with GET/POST/PUT/DELETE for CRUD operations.

Let’s take an example of posts, and perform CRUD operations on it.

var posts = [
{
  id: 1,
  title: 'The Puissant Beast', content: 'Whilst I stand on the footplate of arguably one of the classic superfasts of India'
}
,
{
  id: 2,
  title: 'Authentication Token Mechanism', content: 'Recently, I got a chance to setup a authentication token mechanism on our middleware, which purely exposes REST API\’s.'
}
,
{
  id: 3,
  title: 'Playing with Apache URL Rewrites', content: 'URL Rewriting is one of the interesting concepts that can be employed to improve usability, cleanliness of URLs and also to filter out unwanted URLs at the server level. '
}
,
{
  id: 4,
  title: 'It’s not hosting, it\’s hoisting!', content: 'Developers often get confused with JavaScript scoping. As JavaScript resembles languages like C, it is often assumed it behaves the same way.'
}
];

Let’s try to write the first API which would be a GET HTTP call and fetch all the posts. Following REST naming conventions, let’s name it as /posts

server.route({
method: 'GET', path: '/posts', handler: function (request, response) {
 response(posts);
}
});

See how the request and response objects are passed to the function, and to send back the response, all we need to do is to call response with the actual response to be sent.

In addition to this, we will now write an API which returns a particular post based on it’s ID.

server.route({
method: 'GET', path: '/posts/{id}', handler: function (request, response) {
 if (request.params.id) {
  var post = posts.filter(function (obj) {
  return obj.id == request.params.id;
  });
  post.length === 0 ? response('No posts found') : response(post[0]);
  }
 }
});

Here, we check if there is a post which actually exists for that id and return response accordingly.

Now, proceeding to the third API, we will add a POST call to create new posts.

server.route({
method: 'POST', path: '/posts',
 config: {
  handler: function (request, response) {
  var id = posts.length==0 ? 1: posts[posts.length-1].id+1;
  var post = {
   id: id, title: request.payload.title, content: request.payload.content
  };
  posts.push(post);
  response(post).code(201);
 },
 validate: {
  payload: {
   title: joi.string().required(), content: joi.string().required()
  }
 }
}
});

Here, if you see, we have used joi to do the input parameter validations. This route will create a new post with a new id.

Let’s also include the PUT HTTP call to edit a post and DELETE HTTP call to delete a post.

server.route({
 method: 'PUT', path: '/posts/{id}',
 config: {
  handler: function (request, response) {
   if (request.params.id) {
    var post = posts.filter(function (obj) {
     if (obj.id.toString() === request.params.id) {
      obj.title = request.payload.title;
      obj.content = request.payload.content;
     }
    return obj.id == request.params.id;
    });
    post.length === 0 ? response('No posts found') : response(post[0]);
    }
   else {
    response('ID missing');
   }
  }
 }
});

 

server.route({
 method: 'DELETE',
 path: '/posts/{id}',
  config: {
   handler: function(request, response) {
   var message = "No posts found.";
   if (request.params.id) {
     posts.filter(function(obj, index) {
       if (obj.id.toString() === request.params.id) {
       posts.splice(index, 1);
       message = 'Post deleted';
       }
     });
     response(message);
   } else {
   response('ID missing');
   }
  }
 }
});

Run the server by node index.js. The server will run at http://localhost:3000

So simple to create REST APIs right? We can avoid the overhead of infrastructure and other overheads which are generally needed for performing such operations in other frameworks.

This post only covers the basics and shows how easy it is to create REST APIs using Hapi.js. The complete code is available on Github. There will be a couple of more posts on Hapi.js where I will be targeting on how we can scale this code up to create an application that connects to a database.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s