Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Boom error messages

On my Hapi.js server, I'd like to send a specific message if an account does not have permission rights to access an api endpoint. The Boom message I have right now looks like this:

return reply(Boom.unauthorized("unauthorized access to this API."));

This returns a message that looks like this:

{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "unauthorized access to this API."
}

I would like to make it more customized to look like this:

{
  "success": false,
  "message": "unauthorized access to this API.",
  "csrf-decorator": "",
  "redirect": ""
}

Do we have access to customize the Boom error messages?

Thanks!

like image 261
Atlante Avila Avatar asked Jul 18 '17 23:07

Atlante Avila


2 Answers

Boom comes with built in response error transformation. So in order to achieve my results I had reformat my error reply in the following way:

const error = Boom.forbidden("Sorry, you are restricted in accesssing this API. No soup for you!.");
error.output.statusCode = 403;    // Assign a custom error code
error.output.payload["csrf-decorator"] = request.headers["csrf-decorator"];
error.reformat();
return reply(error);
like image 74
Atlante Avila Avatar answered Sep 18 '22 10:09

Atlante Avila


According to the Hapijs documentation you can reformat error messages to customize them:

Error transformation

Errors can be customized by changing their output content. The boom error object includes the following properties:

  • isBoom - if true, indicates this is a Boom object instance.

  • message - the error message.

  • output - the formatted response. Can be directly manipulated after object construction to return a custom error response. Allowed root keys:

  • statusCode - the HTTP status code (typically 4xx or 5xx).

    • headers - an object containing any HTTP headers where each key is a header name and value is the header content.

    • payload - the formatted object used as the response payload (stringified). Can be directly manipulated but any changes will be lost if reformat() is called. Any content allowed and by default includes the following content:

      • statusCode - the HTTP status code, derived from error.output.statusCode.

      • error - the HTTP status message (e.g. 'Bad Request', 'Internal Server Error') derived from statusCode.

      • message - the error message derived from error.message.

  • inherited Error properties.

It also supports the following method:

  • reformat() - rebuilds error.output using the other object properties.

const Boom = require('boom');

const handler = function (request, h) {
    const error = Boom.badRequest('Cannot feed after midnight');
    error.output.statusCode = 499;    // Assign a custom error code
    error.reformat();
    error.output.payload.custom = 'abc_123'; // Add custom key
    throw error;
});

When a different error representation is desired, such as an HTML page or a different payload format, the onPreResponse extension point may be used to identify errors and replace them with a different response object.

const Hapi = require('hapi');
const Vision = require('vision');

const server = Hapi.server({ port: 80 });
server.register(Vision, (err) => {
    server.views({
        engines: {
            html: require('handlebars')
        }
    });
});

const preResponse = function (request, h) {

    const response = request.response;
    if (!response.isBoom) {
        return h.continue;
    }

    // Replace error with friendly HTML

      const error = response;
      const ctx = {
          message: (error.output.statusCode === 404 ? 'page not found' : 'something went wrong')
      };

      return h.view('error', ctx).code(error.output.statusCode);
};

server.ext('onPreResponse', preResponse);
like image 37
Calvin Alvin Avatar answered Sep 21 '22 10:09

Calvin Alvin