Menu Close

Server-Side Development with Hapi.js — Validating Requests

Hapi.js is a small Node framework for developing back end web apps.

In this article, we’ll look at how to create back end apps with Hapi.js.

Query Parameters

We can validate query parameters with Hapi and Joi.

For example, we can write:

const Joi = require('@hapi/joi');  
const Hapi = require('@hapi/hapi');  
const init = async () => {  
  const server = new Hapi.Server({  
    port: 3000,  
    host: '0.0.0.0',  
  });  
  server.route({  
    method: 'GET',  
    path: '/',  
    handler(request, h) {  
      return request.query.limit;  
    },  
    options: {  
      validate: {  
        query: Joi.object({  
          limit: Joi.number().integer().min(1).max(100).default(10)  
        })  
      }  
    }  
  });  
  await server.start();  
  console.log('Server running at:', server.info.uri);  
};  
process.on('unhandledRejection', (err) => {  
  console.log(err);  
  process.exit(1);  
});  
init();

We set the validate.query property to the object returned with Joi.object .

Then we specify the validation rules for the limit query parameter inside it.

We specified that limit is an integer between 1 and 100 by writing:

Joi.number().integer().min(1).max(100).default(10)

Payload Parameters

Also, we can validate payload parameters by setting the validate.payload property.

For instance, we can write:

const Joi = require('@hapi/joi');  
const Hapi = require('@hapi/hapi');  
const init = async () => {  
  const server = new Hapi.Server({  
    port: 3000,  
    host: '0.0.0.0',  
  });  
  server.route({  
    method: 'POST',  
    path: '/',  
    handler(request, h) {  
      return request.payload;  
    },  
    options: {  
      validate: {  
        payload: Joi.object({  
          post: Joi.string().min(1).max(140),  
          date: Joi.date().required()  
        })  
      }  
    }  
  });  
  await server.start();  
  console.log('Server running at:', server.info.uri);  
};  
process.on('unhandledRejection', (err) => {  
  console.log(err);  
  process.exit(1);  
});  
init();

We set the validate.payload property to an object returned by Joi.object to validate the payload with the properties inside.

post is a string and date is a required date field. It must be in the MM-DD-YYYY format.

So when we make a POST request to the / route with a body like:

{  
    "post": "1",  
    "date": "02-01-2020"  
}

Then we get the payload returned as the response.

Otherwise, we’ll get a 400 response.

Headers

We can also validate headers with Joi in our Hapi app.

For example, we can write:

const Joi = require('@hapi/joi');  
const Hapi = require('@hapi/hapi');  
const init = async () => {  
  const server = new Hapi.Server({  
    port: 3000,  
    host: '0.0.0.0',  
  });  
  server.route({  
    method: 'GET',  
    path: '/',  
    handler(request, h) {  
      return request.state;  
    },  
    options: {  
      validate: {  
        headers: Joi.object({  
          cookie: Joi.string().required()  
        }),  
        options: {  
          allowUnknown: true  
        }  
      }  
    }  
  });  
  await server.start();  
  console.log('Server running at:', server.info.uri);  
};  
process.on('unhandledRejection', (err) => {  
  console.log(err);  
  process.exit(1);  
});  
init();

We set the validate.headers property by setting that to the object returned byJoi.object .

Inside that, we set the cookie property to a required string with:

Joi.string().required()

Then we get the cookie with request.state in our request handler.

So if we send a Cookie header with value data=foo , we get:

{  
    "data": "foo"  
}

as the response.

Conclusion

We can validate various kinds of request content with Hapi and Joi.

Posted in Hapi