首页 文章

如何在使用Joi验证请求时避免Hapi.js发送400错误

提问于
浏览
6

Hapi.js使用Joi failAction 验证 .

情况

我们想使用 Hapi 构建一个“传统的” server-side - only 呈现的应用程序 .

我正在尝试了解如何避免在 Joi 验证失败时向客户端返回“原始” 400 错误:

register-iphone4s-sim

我们想拦截这个“电子邮件不允许为空” validation error 并将其显示在html模板中返回给客户端,而不是简单地返回 400 错误 .

@AdriVanHoudt建议我们应该:

“查看http://hapijs.com/api#route-options下的failAction”

所以我们将 failAction: 'log' 添加到了 /register 路由处理程序:

{
  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!');
}

我期待在终端/控制台中看到错误但是当我尝试 console.loghandler

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

我在GitHub上问了一个问题:https://github.com/hapijs/joi/issues/725但还没有得到一个好的回答 example . 完整代码,如果你有时间帮助:https://github.com/nelsonic/hapi-validation-question

2 回答

  • 9

    有两种简单的解决方案:

    1.使用server.ext('onPreResponse'...

    正如@Clarkie所述,捕获Hapi应用程序中所有错误的一般方法是使用 'onPreResponse' .

    我们编写了一个Hapi插件,它确实如此:https://www.npmjs.com/package/hapi-error

    像往常一样,它有:

    Build Status

    codecov.io

    Code Climate

    Dependency Status

    devDependency Status

    HitCount

    并允许您通过3个简单步骤定义自己的自定义错误页面 .

    1.从npm安装插件:

    npm install hapi-error --save
    

    2.在Hapi项目中包含插件

    当您的服务器 register 包含插件时:

    有关简单示例,请参阅:/example/server_example.js

    3.确保您有一个名为error_template的视图

    注意:hapi-error插件期望您使用Vision(Hapi应用程序的标准视图渲染库),它允许您为模板使用Handlebars,Jade,React等 .

    你的 error_template.html (或 error_template.ext error_template.jsx )应该使用它将传递的3个变量:

    • errorTitle - Hapi生成的错误磁贴

    • statusCode - * HTTP statusCode发送到客户端,例如: 404 (未找到)

    • errorMessage - 人性化的错误消息

    有关示例,请参阅:/example/error_template.html

    而已!

    hapi-error-screens

    2.使用failAction

    Build Status

    codecov.io

    Code Climate

    HitCount

    我们添加了 failAction re-uses register_handler ,以便 registration-form.html 显示任何输入验证错误消息(直到它提交有效数据)

    {
      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 中定义的辅助函数(但会被拆分为可重用的视图助手),这使得我们的处理函数保持精简状态 .

    当我们提交没有任何必填字段的表单时,我们会看到:

    register-1of4

    register-3of4

    我们还使用https://github.com/chriso/validator.js来缓解Cross Site Scripting漏洞:

    register-hack-1of2

    并在成功注册时显示欢迎信息:
    reg-success-1of2

    结论

    我们觉得重新使用处理函数作为 failAction 将代码与此路由/动作保持在一个单独的位置,而 server.ext('onPreResponse' ... (在初始检查时适当)将引入“钩子”,这可能是一个混乱的来源(曾经是一个应用程序)有很多这样的钩子...)

    #YMMV

    让我们知道您的想法!
    Join the chat at https://gitter.im/dwyl/chat

  • 5

    您应该查看在 onPreResponse extension point中实现错误处理程序 .

    可以修改request.response中包含的响应(但不指定新值) . 要返回不同的响应类型(例如,使用HTML响应替换错误),请通过回复(响应)返回新响应 . 请注意,调用reply(response)后生成的任何错误都不会传递回onPreResponse扩展方法以防止无限循环 .

    一个简单的例子:

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

相关问题