hapi-validation-question v1.0.2
hapi-validation-question
Hapi.js Validation with Joi + failAction question.
Situation
We want to build a "traditional" server-side-only rendered application using Hapi.
While trying to understand how to avoid returning a "raw" 400
error to the client when Joi validation fails:

We want to intercept the "email not allowed to be empty" (Joi)
validation error and instead display the error message
in the html template to the client,
rather than returning the 400 error.
@AdriVanHoudt advised that we should:
"Look at
failActionunder http://hapijs.com/api#route-options "
And @MattHarrison elaborated that the failAction should be a function.
Solution
We added failAction which re-uses the register_handler
so that the registration-form.html is shown with any input validation error message (until it is submitted with valid data)
{
method: '*',
path: '/register',
config: {
validate: {
payload : register_fields,
failAction: register_handler // register_handler is dual-purpose (see below!)
}
},
handler: register_handler
}the register_handler is:
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 complete file.
Where extract_validation_error(error) and return_form_input_values(error)
are helper functions defined within server.js (but would be split out into re-useable view helpers) which keep our handler function lean.
When we submit the form without any of the required fields we see:


We also use https://github.com/chriso/validator.js to mitigate Cross Site Scripting vulnerability:

And display a welcome message on successful registration:

Conclusion
We feel that re-using the handler function as the failAction
keeps the code related to this route/action in a single place
whereas server.ext('onPreResponse' ... will introduce "hooks"
which can be a source of confusion (once an app has many such hooks...)