How to avoid Hapi.js sending 400 errors when checking a request with Joi

Hapi.js Validation using the Joi + failAction .

Situation

We want to create a "traditional" server side - only with Hapi .

I am trying to figure out how to avoid returning a "raw" 400 error to the client when the Joi check is complete:

register-iphone4s-sim

We want to intercept this "not allowed to be empty" error message and display it in the html template back to the client, instead of simply returning a 400 error.

@AdriVanHoudt advised that we should:

"Look at failAction under http://hapijs.com/api#route-options "

So, we added failAction: 'log' to the /register route handler:

 { method: '*', path: '/register', config: { validate: { payload : register_fields, failAction: 'log' } }, handler: register_handler } 

See the code in: server.js

register_handler :

 function register_handler(request, reply, source, error) { console.log(request.payload); console.log(' - - - - - - - - - - - - - - - - - - - - -'); console.log(source) console.log(' - - - - - - - - - - - - - - - - - - - - -'); console.log(error) return reply('welcome!'); } 

I expect to see an error in the terminal / console but when I try console.log handler :

 - - - - - - - - - - - - - - - - - - - - - undefined - - - - - - - - - - - - - - - - - - - - - undefined 

I asked a question about GitHub: https://github.com/hapijs/joi/issues/725 but have not yet received an answer with a good example . Full code if you have time to help: https://github.com/nelsonic/hapi-validation-question

+6
source share
2 answers

There are two simple solutions:

1. Use server.ext('onPreResponse' ...

As @Clarkie noted, a common way to catch all the errors in your Hapi application is to use 'onPreResponse' .

We wrote a Hapi plugin that does just that: https://www.npmjs.com/package/hapi-error

As usual, it has:

Build status codecov.io Code Climate Dependency Status devDependency Status Hit count

And it allows you to define your own error pages in 3 easy steps.

1. Install the plugin from npm:

 npm install hapi-error --save 

2. Include the plugin in the Hapi project

Enable the plugin when you register on your server:

See: /example/server_example.js for a simple example.

3. Make sure you have a view called error_template

Note: the hapi-error plugin expects you to use Vision (the standard library for rendering views for Hapi applications) which allows you to use Handlebars, Jade, React, etc. for your templates.

Your error_template.html (or error_template.ext error_template.jsx ) should use 3 variables that it will pass:

  • errorTitle - the error tile generated by Hapi
  • statusCode - * HTTP statusCode sent to the client, for example: 404 (not found)
  • errorMessage - error message for a person

see /example/error_template.html for an example

What is it!

hapi-error-screens

2. Use failAction

Build status codecov.io Code Climate Hit count

We added a failAction that uses register_handler so that registration-form.html displayed with any input validation error message (until it is sent with valid data)

 { method: '*', path: '/register', config: { validate: { payload : register_fields, failAction: register_handler // register_handler is dual-purpose (see below!) } }, handler: register_handler } 

register_handler :

 function register_handler(request, reply, source, error) { // show the registration form until its submitted correctly if(!request.payload || request.payload && error) { var errors, values; // return empty if not set. if(error && error.data) { // means the handler is dual-purpose errors = extract_validation_error(error); // the error field + message values = return_form_input_values(error); // avoid wiping form data } return reply.view('registration-form', { title : 'Please Register ' + request.server.version, error : errors, // error object used in html template values : values // (escaped) values displayed in form inputs }).code(error ? 400 : 200); // HTTP status code depending on error } else { // once successful, show welcome message! return reply.view('welcome-message', { name : validator.escape(request.payload.name), email : validator.escape(request.payload.email) }) } } 

See: server.js : 57 for the full file.

Where extract_validation_error(error) and return_form_input_values(error) are helper functions defined inside server.js (but will be divided into reusable view helpers) that save our lean handler function.

When we submit the form without any required fields, we see:

<T411>

register-3of4

We also use https://github.com/chriso/validator.js to mitigate the scripts for multiple sites vulnerability:

register-hack-1of2

And display a welcome message about successful registration: reg-success-1of2

Conclusion

We believe that reusing the handler function as failAction saves the code associated with this route / action in one place whereas server.ext('onPreResponse' ... (with the appropriate initial inspection) introduces “hooks”, which may be the source confusion (when the application has many such hooks ...)

#YMMV

Let us know what you think! Join the chat at https://gitter.im/dwyl/chat

+8
source

You should look at the implementation of the error handler at the onPreResponse extension point .

The response contained in request.response can be changed (but no new value assigned). To return a different type of response (for example, replace the error with an HTML response), return the new answer through the response (response). Please note that any errors that occur after calling the response (answer) will not be passed back to the onPreResponse extension onPreResponse to prevent an infinite loop.

A simple example:

 server.ext('onPreResponse', function (request, reply) { if (request.response.statusCode === 400 ){ return reply('summat else'); } return reply.continue(); }); 
+5
source

All Articles