Skip to main content

Hapi.js Overview

Introduction to Hapi.js

Hapi.js is a rich and powerful framework for building web applications and services in Node.js. It provides a robust set of features and plugins to simplify the development process and make building scalable and secure applications easier.

History

Hapi.js was created by Eran Hammer and was first released in 2011. It was initially developed as an internal project at Walmart to handle their e-commerce platform. Later, it was open-sourced and gained popularity among the Node.js community due to its unique features and extensibility.

Features

1. Routing

Hapi.js provides a flexible and declarative routing system. It allows you to define routes with different HTTP methods, URL parameters, and query parameters. Here's an example:

const Hapi = require('hapi');

const server = Hapi.server({
port: 3000,
host: 'localhost'
});

server.route({
method: 'GET',
path: '/hello/{name}',
handler: (request, h) => {
return `Hello, ${request.params.name}!`;
}
});

async function startServer() {
await server.start();
console.log('Server running at:', server.info.uri);
}

startServer();

In the above example, we define a route that listens for GET requests at the path "/hello/{name}". When a request is made to this route, the server responds with a greeting message containing the name parameter provided in the URL.

2. Request Lifecycle

Hapi.js provides a detailed request lifecycle, allowing you to handle various stages of a request. This includes authentication, validation, pre-processing, and response generation. You can define plugins and hooks at different stages of the request lifecycle to extend the functionality. Here's an example:

server.ext('onPreHandler', (request, h) => {
console.log('Request received:', request.path);
return h.continue;
});

In this example, we use the server.ext method to define a pre-handler hook. This hook is executed before the handler function for each incoming request. We log the path of the request and continue the request lifecycle by calling h.continue.

3. Authentication and Authorization

Hapi.js provides built-in support for authentication and authorization. It allows you to easily integrate different authentication strategies such as session-based, token-based, or OAuth. You can also define access control rules to restrict access to certain routes or resources. Here's an example:

const Bcrypt = require('bcrypt');
const users = {
john: {
username: 'john',
password: '$2b$10$1Kxv7iXq3c7gjQJ8M6jMduPp2z5mIYF2uNt7Q0mZyWn7pI1n6Xm2e' // 'password'
}
};

const validateUser = async (request, username, password, h) => {
const user = users[username];
if (!user) {
return { credentials: null, isValid: false };
}
const isValid = await Bcrypt.compare(password, user.password);
return { credentials: { id: user.id, name: user.name }, isValid };
};

server.auth.strategy('basic', 'basic', { validate: validateUser });

server.route({
method: 'GET',
path: '/private',
options: {
auth: 'basic'
},
handler: (request, h) => {
return `Welcome, ${request.auth.credentials.name}!`;
}
});

In this example, we define a basic authentication strategy using the server.auth.strategy method. We provide a validation function that checks the username and password against the stored user credentials. The validateUser function uses Bcrypt to compare the password hash. We then apply this authentication strategy to a route by setting the auth option.

4. Plugins and Extensibility

Hapi.js has a rich ecosystem of plugins that can be easily integrated into your application. These plugins provide additional features like logging, caching, database integration, and more. You can also create your own plugins to extend the functionality of your application. Here's an example of using the hapi-auth-jwt2 plugin for JWT authentication:

const HapiJwt = require('hapi-auth-jwt2');

await server.register(HapiJwt);

const validateUser = async (decoded, request, h) => {
const user = await User.findById(decoded.id);
if (!user) {
return { isValid: false };
}
return { isValid: true };
};

server.auth.strategy('jwt', 'jwt', {
key: 'your_secret_key',
validate: validateUser
});

server.route({
method: 'GET',
path: '/private',
options: {
auth: 'jwt'
},
handler: (request, h) => {
return `Welcome, ${request.auth.credentials.name}!`;
}
});

In this example, we register the hapi-auth-jwt2 plugin using the server.register method. We then define a JWT authentication strategy using the server.auth.strategy method. The validateUser function is called to validate the decoded JWT token and retrieve the user from the database. Finally, we apply the jwt authentication strategy to a route.

Examples

For more examples and detailed documentation, you can visit the official Hapi.js website. The website provides comprehensive guides, tutorials, and API references to help you get started with Hapi.js and explore its features in-depth.

Overall, Hapi.js is a powerful and versatile framework for building web applications and services in Node.js. Its extensive set of features, strong plugin ecosystem, and clear documentation make it a popular choice among developers.