如何避免在Joivalidation请求时Hapi.js发送400错误
Hapi.jsvalidation与Joi + failAction
问题。
情况
我们希望使用Hapi构build一个“ 传统的 ” 仅 服务器端渲染的应用程序。
我试图了解如何避免在Joi
validation失败时将“ 原始 ” 400
错误返回给客户端:
我们想拦截这个“ 不允许为空的电子邮件 ” validation错误,并将其显示在客户端的html模板中,而不是简单地返回400
错误。
@AdriVanHoudtbuild议我们应该:
“看看http://hapijs.com/api#route-options下的failAction”
所以我们添加了failAction: 'log'
到/register
path处理器:
{ method: '*', path: '/register', config: { validate: { payload : register_fields, failAction: 'log' } }, handler: register_handler }
请参阅: 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!'); }
我期待在terminal/控制台中看到一个错误,但是当我尝试console.log
handler
:
- - - - - - - - - - - - - - - - - - - - - undefined - - - - - - - - - - - - - - - - - - - - - undefined
我问了关于GitHub的问题: https : //github.com/hapijs/joi/issues/725,但还没有得到一个好 例子的答案。 完整的代码,如果你有时间来帮忙: https : //github.com/nelsonic/hapi-validation-question
有两个简单的解决scheme:
1.使用server.ext('onPreResponse' ...
正如@Clarkie指出的那样,在您的Hapi App中捕获所有错误的一般方法是使用'onPreResponse'
。
我们写了一个Hapi插件,它的确如此: https : //www.npmjs.com/package/hapi-error
像往常一样,它有 :
而且可以通过3个简单的步骤定义自己的自定义错误页面。
1.从npm安装插件 :
npm install hapi-error --save
2.将该插件包含在您的Hapi项目中
在register
服务器时join插件:
有关简单示例,请参见/example/server_example.js
3.确保您有一个名为error_template
的视图
注意:
hapi-error
插件期望您使用Vision
( Hapi应用程序的标准视图渲染库 ),它允许您为模板使用Handlebars,Jade,React等。
你的error_template.html
( 或error_template.ext
error_template.jsx
)应该使用它将被传递的3个variables:
-
errorTitle
– 由Hapi生成的错误图块 -
statusCode
– *发送到客户端的HTTP statusCode, 例如:404
( 未find ) -
errorMessage
– 人性化的错误信息
例如,请参阅:
/example/error_template.html
就是这样 !
2.使用failAction
我们添加了failAction
,它重新使用了register_handler
,使得registration-form.html
显示了任何inputvalidation错误消息( 直到它被提交了有效数据 )
{ 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) }) } }
完整的文件请参见: server.js :57 。
其中extract_validation_error(error)
和return_form_input_values(error)
是在server.js
定义的辅助函数( 但是会被分解为可重用的视图助手 ),这使得我们的处理函数变得精简。
当我们提交没有任何必填字段的表单时,我们会看到:
我们还使用https://github.com/chriso/validator.js来缓解跨站点脚本漏洞:
并显示一个成功注册的欢迎消息:
结论
我们觉得重新使用处理函数作为failAction
可以将与这个路由/动作相关的代码保存在一个地方,而server.ext('onPreResponse' ...
( 虽然在初始检查时是合适的 )会引入“ hooks ”是一个混乱的来源( 一旦一个应用程序有很多这样的钩子… )
#YMMV
让我们知道您的想法!
你应该看看在onPreResponse
扩展点实现一个error handling程序。
request.response中包含的响应可能会被修改(但不会被分配一个新的值)。 要返回不同的响应types(例如,用HTML响应replace错误),请通过回复(响应)返回新响应。 请注意,调用回复(响应)后生成的任何错误都不会被传回
onPreResponse
扩展方法,以防止无限循环。
一个简单的例子:
server.ext('onPreResponse', function (request, reply) { if (request.response.statusCode === 400 ){ return reply('summat else'); } return reply.continue(); });