An Introduction to hapi
hapijs is one of the most popular Nodejs frameworks also known for its boilerplate approach. The reason why “hapi makes happy “ is it deals “more with configuration and less with code. “ hapi framework is the ideal option to stick with when you are planning to build a restful API.

Let us examine the simpilicty of hapi with an example. Lets create a simple restful API using hapi and database Mysql.

First make sure that you have Nodejs and npm installed in your system. Then we can go with our first hapi project.

1: Install hapi and dependencies

Like every project, hapi needs a root folder. Lets create that , say API.

See below is the final folder structure that we are going to have when we finish this post. Lets just go through it and we can create and explain what is it for, as the post progress.

hapi structure

Then create  a package.json file inside that and lets have the following code in that file. 

"name": "MakeMeHapi",

 "version": "0.0.1",

 "main": "app.js",

 "dependencies": {

   "hapi": "latest",

   "hapi-swagger": "^6.1.0",

   "inert": "^4.0.0",

   "vision": "^4.1.0",

   "joi": "latest",

   "mysql":"latest”

 }

}

 name : name of  the project ( your choice)

version: version of the project (your choice)

main : We need a main file for our applications (your choice , here app.js)

dependencies: The dependencies we needed. Lets have hapi (our framework),hapi-swagger(the hapi provided plugin for automatic api documentation), inert(Static file and directory handlers for hapi.js), vision (Templates rendering support for hapi.js),joi(validation) and mysql(our database)

We have our package .json file is ready for installation. Run the following command.

$ npm install

Now we have hapi and all other dependencies got installed and are ready to use. We can use these in our application and can examine how to call them.
In our package.json file, we mentioned that our main app file is app.js. This is the first application level file for our project. This file makes use of our above installed dependencies.

2: Create our first hapi file

Create a js file app.js and place it in root folder where our package.json file is. The very basic look of app.js is as follows.

use strict';

const hapi                  = require('hapi');    // this will include our hapi framework package

const server                = new hapi.Server(); // create a server object

const Pack                 =  require('./package'); // simply include our package.json file



//Now establish a connection using our server object.

server.connection({

   host: 'localhost',

   port: 3000 // make sure port is available and open (you are free to choose any availabe/open port)

});

//start the server

server.start((err) => {

   if (err) {

       throw err;

   }

   console.log('Server running at:', server.info.uri);

});

This is our basic app.js file. We can make sure that its working by simply running the following . First move to API folder and then

$ node app.js

You will get the output as follows:

Server running at: http://localhost:3000
Done. We have achieved our first goal.

3: Routes
Now, let us check how to output a result in your browser. So just modify our app.js as follows.

'use strict';

const hapi                  = require('hapi');    // this will include our hapi framework package

const server                = new hapi.Server(); // cretae a server object

const Pack                 =  require('./package'); // simple include our package.json file


//Now establish a connection using our server object.

server.connection({

   l,

   port: 3000 // make sure port is available and open

});

//The API will respond to GET requests on the / user endpoint.

server.route([{

       method: 'GET',// the method

       path: '/user',

       handler: function (request, reply) {

           //request holds the request params and reply for output

           reply(“welcome to my first hapi app”);

       }

   }]);
//start the server

server.start((err) => {

   if (err) {

       throw err;

   }

   console.log('Server running at:', server.info.uri);

});

Server.route is the function that responsible for this. It will accept the GET request from /user and handler handles the request and replies with the result.

Since we have done some changes in our js file Run

$ node app.js

Now, view this in your bowser . Just browser  http://localhost:3000/user

welcome to my first hapi app

4: Plugins and  Registers

Now, we can examine how to add more routes with GET / POST etc and keep separate files for each of them. In the above app.js we are using server.route() for our routing functions. We can have as many server.routes() in this app.js. But inorder to make a structured format, we can move our server.route()  to a new file called user.js. Create a new folder “routes” in root folder and create a new file user.js within this folder.

exports.register = function (server,options,next)

{

      server.route([{

           method: 'GET',// the method

           path: '/user',

          handler: function (request, reply) {

             //request holds the request params and reply for output

              reply(“welcome to my first hapi app: Now using plugins!!”);

           }

       }]);

    next();

}

exports.register.attributes = {

   name    :'user-route',

   version : '0.0.1'

};

By this we have created a plugin for our /user end point. The creation of a plugin is via exports.register  and the creation function holds three params

1: server (the server object),

2: options(this is the option that we passed to this when we call this plugin: How to call this plugin will explain later)

3: next (is the default callback function that finish the plugin creation)

For every plugin we create like this, we need to set a unique name attribute. For that we use exports.register.attributes

Now, we have created our user plugin.  We need to register this plugin. We are going to register this in our app.js . So let us rewrite our app.js as follows.

'use strict';

const hapi                  = require('hapi');    // this will include our hapi framework package

const server                = new hapi.Server(); // cretae a server object

const Pack                 =  require('./package'); // simple include our package.json file

//Now establish a connection using our server object.

server.connection({

   host: 'localhost',

   port: 3000 // make sure port is available and open

});

//register the user plugin

server.register(


   [

       {

           register    :   require('./routes/user.js'),  // register by providing the path of the user.js file.Note that

                                                                                            now we have a change in path, a new routes folder

           options     :   {

                                  message:'hello'  //this is act as the second param in creation function of user.js. We can

                                                                           get this value in that functions as  options.message

                                }

       }

]

);

//start the server

server.start((err) => {

   if (err) {

       throw err;

   }

Since we have done some changes in our js file Run

$ node app.js

If you check your browser http://localhost:3000/user

welcome to my first hapi app: Now using plugins!!

Similarly, we can register any plugins either we created or hapi provided via server.register(), just by adding as next key of  the array.

Similary, if we are registering the hapi plugin, hapi-swagger (no need to create it as it is already created plugin of hapi 🙂 , just need to register it in our app) we can register it as follows:

server.register(

   [

//register the user plugin

       {

           register    :   require('./routes/user.js'),  // register by providing the path of the user.js file

           options     :   {

                                  message:'hello'  //this is act as the second param in creation function of user.js. We can

                                                                           get this value in that functions as  options.message

                                }

       },

      {

           register    : require('hapi-swagger'),

           options     : {

                               info :{

                                   title  : 'api application',

                                   version:  '0.0.1'

                               }

                         }

       },

]

);

(We will check how to use this hapi-swagger later in this blog. Be patient !). Now let us see how to set up mysql for our app.

5: Mysql db connection

First create a mysql db say apidb and create a table apiuser and have the fileds: id and name .

Id Name
1 John

Create a new file database.js in the same root folder where we have our package.js , app.js

var mysql           = require('mysql');  // include the mysql plugin

//setup the connection

var connection = mysql.createConnection({

 host     : 'localhost',

 user     : 'dbusername',

 password : 'dbpassword',

 database : 'apidb'

});

//connect. (actually can also connect when we call a query )

connection.connect(function(err) {

   if (err) {

     console.error('error connecting: ' + err.stack);

     return;

   }

   else{

        console.log('mysql started');

   }

});

//export this module , then only we can use this in other files

module.exports = {

 connection: connection

}

6: POST ,Validate (Joi Module)  and Save

Now, let us create a new adduser plugin and call the db in that file. Here we can discuss the use of joi module that we have installed on our very first step.

adduser.js in routes folder

const db            = require('../database.js'); // include the database file and get the db object

const Joi           =  require('joi');//include the joi module for validation

exports.register = function(server,options,next)

{

   server.route([{

           method: 'POST',

           path:   '/adduser',

           config: {

                  tags : ['api'], // let it be here for now. I will explain it later in this blog

               // We use Joi plugin to validate request

               validate: {

                   payload: {

                       // Both name and id are required fields

                       name: Joi.string().required(),

                       id: Joi.number().required()

                   }

               }

           },

           handler: function(request,reply)

           {

                   var post = {name:request.payload.name,id:request.payload.id};

                   db.connection.query(

                       'INSERT INTO apiuser set?',post,

                       function(err, rows) {

                           reply([{

                                   statusCode: 200,

                                   message: 'Inserted successfully',

                               }]);

                         if(err) {

                           throw new Error(err)

                         }

                       }

                     )               

           }

   }]);

   next();

};

exports.register.attributes = {

   name    :'adduser-route',

   version : '0.0.1'

};

Here, we are first including our db file and joi module. We created a new route for adding  user details to our db table based on user input name and id. Both the fileds here, namely, id and name are required ones, we  use joi module for validation. Set that in config portion inside the route. “payload” refers to the name of array that holds the values. When we call this adduser api without the name/id or any invalid value then we will get the error message (Joi 🙂 ). Note that Joi will not work with GET method.

For saving to db , we collect the values corresponding to each filed and call mysql query with the help of db object and return a success message.

Now we have our adduser.js ready. Save this in same root folder where we have package.json,app.js and user.js.

Register this plugin in our main app.js. See below.

'use strict';

const hapi                  = require('hapi');    // this will include our hapi framework package

const server                = new hapi.Server(); // cretae a server object

const Pack                 =  require('./package'); // simple include our package.json file



//Now establish a connection using our server object.

server.connection({

   host: 'localhost',

   port: 3000 // make sure port is available and open

});

//register the user plugin

server.register(
   [

//register the user plugin

       {

           register    :   require('./routes/user.js'),  // register by providing the path of the user.js file

           options     :   {

                                  message:'hello'  //this is act as the second param in creation function of user.js. We can

                                                                           get this value in that functions as  options.message

                                }

       },


      {

           register    : require('hapi-swagger'),

           options     : {

                               info :{

                                   title  : 'api application',

                                   version:  '0.0.1'

                               }

                         }

       },

       {

           register    :   require('./routes/adduser.js'),  // register by providing the path of the adduser.js file

           options     :   {

                                }

       },        

]

);

//start the server

server.start((err) => {

   if (err) {

       throw err;

   }

   console.log('Server running at:', server.info.uri);

});

Ok. Now we need to test this. Since it is an API, use some API tool for testing. You can use any API testing tools like postman plugin of chrome , or restclient for Firefox etc.  hapi has its own api testing client hapi-swagger. We have installed it and registed it in app.js.  But need to configure that. Also we need to examine how to make use of controllers and models for a more structural format. Shall we discuss that on next week ? My kid is already getting restless, just don’t want to let him throw a tantrum, but I promise to be back with the next part of this blog this Monday,  catch you then. take care.

Read Hapijs Introduction Part 2

Latest Post