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 Set Up a Multi-Node Kafka Cluster using KRaft

Setting up a multi-node Kafka cluster using KRaft (Kafka Raft) mode involves several steps. KRaft mode enables Kafka to operate without the need for Apache ZooKeeper, streamlining the architecture and improving management. Here’s a comprehensiv …

read more

Streamline Data Serialization and Versioning with Confluent Schema Registry …

Using Confluent Schema Registry with Kafka can greatly streamline data serialization and versioning in your messaging system. Here's how you can set it up and utilize it effectively: you can leverage Confluent Schema Registry to streamline data seria …

read more