Hapi.js Validation with Joi + failAction question.
GPL-2.0 License
Hapi.js Validation with Joi + failAction
question.
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
failAction
under http://hapijs.com/api#route-options "
And @MattHarrison elaborated that the failAction
should be a function.
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:
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...)
Let us know what you think!