Joi 验证仅返回一条错误消息
Posted
技术标签:
【中文标题】Joi 验证仅返回一条错误消息【英文标题】:Joi validation return only one error message 【发布时间】:2014-11-15 05:34:30 【问题描述】:我有一个由名称字段、电子邮件字段和文本区域组成的三字段表单。我正在使用 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()
为了解释,假设不填写这三个字段。我只收到一个消息错误,而不是其他字段的消息错误。为什么?
【问题讨论】:
【参考方案1】:这是因为 Joi 默认提前中止。
abortEarly
- 当true
时,对第一个错误停止验证,否则返回找到的所有错误。默认为true
。
*编辑: hapi 8.0 中的配置已更改。您需要将abortEarly: false
添加到routes
配置中:
var server = new Hapi.Server();
server.connection(
host: 'localhost',
port: 8000,
routes:
validate:
options:
abortEarly: false
);
*有关详细信息,请参阅Joi API documentation。
*另外,请参阅Hapi Route options 下的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 配置为返回所有错误。为此,您需要将abortEarly
设置为false
。您可以在服务器配置中执行此操作:
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' ]
【讨论】:
【参考方案2】:validation
键不再适用于 Hapi 8.0 中的 Hapi.Server
构造函数:
[1] 不允许验证
我在GitHub issue for hapi 中找到了解决方案:
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);
);
【讨论】:
【参考方案3】:我没有与 hapi.js 集成,但我注意到有一个可以传递的 ValidationOptions
对象。该对象内部是一个abortEarly
选项,因此应该可以:
Joi.validate(request, schema, abortEarly: false
也可以这样配置:
Joi.object().options( abortEarly: false ).keys(...);
查看这些类型定义以了解更多ValidationOptions
:
https://github.com/DefinitelyTyped/tsd/blob/master/typings/joi/joi.d.ts
【讨论】:
它在 2020 年仍然可以使用 node v12.18.0 和 hapi 17.1.1,谢谢为我节省了很多时间? 完美运行!【参考方案4】:经过一番研究,我发现可以通过两种方式解决:
[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`,
),
)
【讨论】:
以上是关于Joi 验证仅返回一条错误消息的主要内容,如果未能解决你的问题,请参考以下文章