How to create a REST API with Hapi Js Framework in Node Js

Hapi is the best framework to create the REST API easily without time wasting.

Here we are creating REST API for User Collections with MongoDB as the database.

So as you know for working with Hapi Framework you need to install Node Js in your system.

For creating REST API with Hapi Framework you need to follow these steps:-

1.Create a folder where you want to build your REST API.

C:\Hapi-Rest-Api

3.Now run the npm init command for creating the package.json file.

4.After creating the package.json file install the Hapi Framework and following supporting node modules.

          
            npm install hapi --save  
            npm install boom --save  
            npm install good --save  
            npm install good-console --save  
            npm install good-squeeze --save  
            npm install joi --save  
            npm install mongojs --save  
            npm install node-uuid --save  
        
    

5.As soon you installed these Node modules your package.json file will update and save all the dependencies.

6.Now you need to create the server.js file for creating the REST API. Here in server.js file you need to import the Hapi framework and good module for display the access log info in console

7.Then you create the object of the hapi framework and create the server & connection with that object.

     
        'use strict';  

        const Hapi = require('hapi'); 
        const Good = require('good');  
        const server = new Hapi.Server(); 
        server.connection({ 
        port: 3000, 
        host: 'localhost' 
        });  

        server.route({     
        method: 'GET',     
        path: '/',     
        handler: function (request, reply) {         
        reply('Welcome to the Hapi Rest API Service');     
        } 
        });  

        server.register([{     
        register: Good,     
        options: {         
        reporters: {             
        console: [{                 
        module: 'good-squeeze',                 
        name: 'Squeeze',                 
        args: [{                     
        response: '*',                     
        log: '*'                 
        }]             
        }, {                 
        module: 'good-console'             
        }, 'stdout']         
        }     
        } 
        }, 
        require('./src/routes/users') ], (err) => {      
        if (err) {         
        throw err;     
        }      
        server.start((err) => {         
        if (err) {             
        throw err;         
        }         

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

8.Then create the src folder for all the routes, controller and model related files and create the files as well.

 src/routes/routes.js  
 src/controller/users.js  
 src/model/users.js 

9.Now create the routes file as below in code.

 
'use strict';  

const Joi = require('joi');  
const UsersController = require('../controllers/users');  

exports.register = function(server, options, next) {      
var usersController = new UsersController();      

server.route({           
method: 'GET',         
path: '/v1/users',         
handler: usersController.index,         
config: {         
validate: {         
headers: {     
'user-agent': Joi.string().required()     
},     
options: {         
allowUnknown: true     
}         
}         
}     
});      

server.route({           
method: 'GET',         
path: '/v1/users/{id}',         
handler: usersController.show,         
config: {         
validate: {         
headers: {     
'user-agent': Joi.string().required()     
},     
options: {         
allowUnknown: true     
},     
params: {                 
id: Joi.string().min(3).max(100)             
}         
}         
}     
});      

server.route({           
method: 'POST',         
path: '/v1/users',         
handler: usersController.store,         
config: {             
validate: {             
headers: {     
'user-agent': Joi.string().required()     
},     
options: {         
allowUnknown: true     
},                 
payload: {                     
first_name: Joi.string().min(3).max(50).required(),                     
last_name: Joi.string().min(3).max(50).required(),                     
email: Joi.string().email().required(),                     
phone_number: Joi.string().min(10).max(10).required(),                     
user_type: Joi.string().min(3).max(15).required(),                     
create_date: Joi.date().iso(),                     
update_date: Joi.date().iso(),                     
status: Joi.string()                 
}             
}         
}     
});      

server.route({           
method: 'PATCH',         
path: '/v1/users/{id}',         
handler: usersController.update,         
config: {             
validate: {             
headers: {     
'user-agent': Joi.string().required()     
},     
options: {         
allowUnknown: true     
},     
params: {                 
id: Joi.string().min(3).max(100)             
},                 
payload: Joi.object({                     
first_name: Joi.string().min(3).max(50).required(),                     
last_name: Joi.string().min(3).max(50).required(),                     
email: Joi.string().email().required(),                     
phone_number: Joi.string().min(10).max(10).required(),                     
user_type: Joi.string().min(3).max(15).required(),                     
create_date: Joi.date().iso(),                     
update_date: Joi.date().iso(),                     
status: Joi.string()                 
}).required().min(1)             
}         
}     
});          

server.route({           
method: 'DELETE',         
path: '/v1/users/{id}',         
handler: usersController.destroy,         
config: {         
validate: {         
headers: {     
'user-agent': Joi.string().required()     
},     
options: {         
allowUnknown: true     
},     
params: {                 
id: Joi.string().min(3).max(100)             
}         
}         
}     
});      

return next(); 
};  

exports.register.attributes = {   
name: 'routes-users' 
}; 

10.After route file there is a controller file and model files create both and import as shown in below code.

controller/users.js

 
'use strict';  

const UsersModel = require('../models/users'); 
const usersModel = new UsersModel();  

function UsersController(){};  

/* Get All Users */ 

UsersController.prototype.index = function(request, reply) {      
usersModel.getAllUsers(request, reply); 
};  

/* Get Single User */ 

UsersController.prototype.show = function(request, reply) {      
usersModel.getUser(request, reply); 
};  

/* Add Single User */ 

UsersController.prototype.store = function(request, reply) {      
usersModel.addUser(request, reply); 
};  

/* Update Single User */ 

UsersController.prototype.update = function(request, reply) {      
usersModel.updateUser(request, reply); 
};  

/* Delete Single User */ 

UsersController.prototype.destroy = function(request, reply) {      
usersModel.destroyUser(request, reply); 
};  

module.exports = UsersController; 

models/users.js

 
'use strict';  

const Boom = require('boom');   
const uuid = require('node-uuid');    
const mongojs = require('mongojs');  
const db = mongojs('HapiRESTAPI', ['users']);  

function UsersModel(){};  

/* Get All Users */ 

UsersModel.prototype.getAllUsers = function(request, reply) {        
db.users.find((err, docs) => {         
if (err) {             
return reply(Boom.wrap(err, 'Internal MongoDB error'));         
}         

reply(docs);     
}); 
};  

/* Get Single User */ 

UsersModel.prototype.getUser = function(request, reply) {        
db.users.findOne({         
_id: request.params.id     
}, (err, doc) => {         
if (err) {             
return reply(Boom.wrap(err, 'Internal MongoDB error'));         
}         

if (!doc) {             
return reply(Boom.notFound());         
}         

reply(doc);     
}); 
};  

/* Add Single User */ 

UsersModel.prototype.addUser = function(request, reply) {         
const user = request.payload;     
user._id = uuid.v1();      
db.users.save(user, (err, result) => {         
if (err) {             
return reply(Boom.wrap(err, 'Internal MongoDB error'));         
}         

reply(user);     
}); 
};  

/* Update Single User */ 

UsersModel.prototype.updateUser = function(request, reply) {         
db.users.update({         
_id: request.params.id     
}, {         
$set: request.payload     
}, function (err, result) {         
if (err) {             
return reply(Boom.wrap(err, 'Internal MongoDB error'));         
}         

if (result.n === 0) {             
return reply(Boom.notFound());         
}         

reply(result).code(200);     
}); 
};  

/* Delete Single User */ 

UsersModel.prototype.destroyUser = function(request, reply) {         
db.users.remove({         
_id: request.params.id     
}, function (err, result) {         
if (err) {             
return reply(Boom.wrap(err, 'Internal MongoDB error'));         
}         

if (result.n === 0) {             
return reply(Boom.notFound());         
}         

reply(result).code(200);     
}); 
};  

module.exports = UsersModel; 

Here in this tutorial we are using mongojs for accessing and making the connection with MongoDB

We are using Boom module for error handling.

We are using Joi module for payload and request validation.

We are using node-uuid module for generating unique object id for inserting in to the database the collection documents

So this is the whole tutorial for creating REST API with HAPI JS you can find the code on git hub.
https://github.com/eranilkapoor/hapi-rest-api

How to Deploy Python Application on Kubernetes with Okteto

Deploying a Python application on Kubernetes with Okteto involves setting up your Kubernetes cluster, creating a Docker container for your Python application, and using Okteto to deploy the application on your Kubernetes cluster. Okteto is a platform …

read more

Explain the concept of streams in Node.js. How are they used, and what are …

In Node.js, streams are powerful mechanisms for handling data transfer, especially when dealing with large amounts of data or performing I/O operations. Streams provide an abstraction for handling data in chunks, rather than loading entire datasets i …

read more