38

我有一个由名称字段、电子邮件字段和文本区域组成的三字段表单。我正在使用 Joi 4.7.0 版本和 hapijs。我使用下面的对象验证输入。我从 ajax 调用接收数据对象。当我用错误信息填写所有三个字段时,我只会得到与第一个错误字段相关的消息。像那样:

"{"statusCode":400,"error":"Bad Request","message":"name is not allowed to be empty","validation":    {"source":"payload","keys":["data.name"]}}"

validate: {
      payload: {
        data: {
          name: Joi.string().min(3).max(20).required(),
          email: Joi.string().email().required(),
          message: Joi.string().min(3).max(1000).required()
        }
      }
}

为了解释,假设不填写这三个字段。我只收到一个消息错误,而不是其他字段的消息错误。为什么?

4

4 回答 4

47

发生这种情况是因为 Joi 默认提前中止。

abortEarly- when true,对第一个错误停止验证,否则返回找到的所有错误。默认为true.

*编辑: hapi 8.0 中的配置已更改。您需要添加abortEarly: falseroutes配置:

var server = new Hapi.Server();
server.connection({
    host: 'localhost',
    port: 8000,
    routes: {
        validate: {
            options: {
                abortEarly: false
            }
        }
    }
});

*有关更多详细信息,请参阅Joi API 文档
*另外,请参阅Hapi 路线选项validation下。

所以 Joi 在第一个错误时停止验证:

var Hapi = require('hapi');
var Joi = require('joi');

var server = new Hapi.Server('localhost', 8000);

server.route({
    method: 'GET',
    path: '/{first}/{second}',
    config: {
        validate: {
            params: {
                first: Joi.string().max(5),
                second: Joi.string().max(5)
            }
        }
    },
    handler: function (request, reply) {

        reply('example');
    }
});

server.start();

server.inject('/invalid/invalid', function (res) {

    console.log(res.result);
});

输出:

{ statusCode: 400,
  error: 'Bad Request',
  message: 'first length must be less than or equal to 5 characters long',
  validation: { source: 'params', keys: [ 'first' ] } }

但是,您可以将 Hapi 配置为返回所有错误。为此,您需要设置abortEarlyfalse. 您可以在服务器配置中执行此操作:

var server = new Hapi.Server('localhost', 8000, { validation: { abortEarly: false } });

如果你现在运行脚本,你会得到:

{ statusCode: 400,
  error: 'Bad Request',
  message: 'first length must be less than or equal to 5 characters long. second length must be less than or equal to 5 characters long',
  validation: { source: 'params', keys: [ 'first', 'second' ] } }
于 2014-09-21T07:06:00.290 回答
32

我没有与 hapi.js 集成,但我注意到有一个ValidationOptions可以传递的对象。该对象内部是一个abortEarly选项,因此应该可以:

Joi.validate(request, schema, { abortEarly: false }

这也可以配置如下:

Joi.object().options({ abortEarly: false }).keys({...});

查看这些类型定义了解更多信息ValidationOptionshttps ://github.com/DefinitelyTyped/tsd/blob/master/typings/joi/joi.d.ts

于 2017-04-26T08:08:02.383 回答
4

validation键不再适用Hapi.Server于 Hapi 8.0 中的构造函数:

[1] 不允许验证

我在hapi 的 GitHub 问题中找到了解决方案:

var Hapi = require('hapi');


var server = new Hapi.Server();

server.connection({
  host: HOST,
  port: PORT,
  routes: {
    validate: {
      options: {
        abortEarly: false
      }
    }
  }
});

// Route using Joi goes here.
server.route({});

server.start(function () {
  console.log('Listening on %s', server.info.uri);
});
于 2014-12-22T23:50:09.360 回答
0

经过一番研究,我发现它可以通过两种方式解决:

[Segments.BODY]: Joi.object().keys({
value: Joi.string().required().error(new Error('Value is required and has to be a text!')),
})

或者

[Segments.BODY]: Joi.object().keys({
password: Joi.string().required().pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')).min(8).label('Password').messages({
    'string.pattern.base': 'Your {#label} does not matche the suggested pattern',
    'string.base': `Your {#label} should match the suggested pattern`,
    'string.empty': `Your {#label} can not be empty`,
    'string.min': `Your {#label} has to be at least {#limit} chars`,
    'any.required': `Your {#label} is required`,
}),
})
于 2020-07-01T06:16:35.343 回答