我有一个由名称字段,电子邮件字段和textarea组成的三个字段表单。我使用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()
}
}
}
为了解释,我们假设不填写三个字段。我只收到一条消息错误,而不是其他字段的消息错误。为什么呢?
答案 0 :(得分:28)
这是因为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' ] } }
答案 1 :(得分:10)
我没有与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
答案 2 :(得分:4)
{HAPi 8.0中的validation
密钥不再适用于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 :(得分: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`,
}),
})