Hapijs和Joi:用存在validation查询参数:'禁止'

我的目标是为post创build索引路线。 用户应该能够指定一些查询参数(即标签,types),但不应该能够指定其他。 澄清:

这是好的:

/posts /posts?tags=food /posts?type=regular&tags=stackoverflow 

这不好:

 /posts?title=Hello 

这是hapi包configuration:

 servers: [ { host: 'localhost', port: 3000, options: { labels: ["api"], validation: { abortEarly: false, presence: 'forbidden' } } } ], 

请注意presence: forbidden选项。

这是路由configuration:

 handler: function (request, reply) { Post.find(request.query, function (err, posts) { if(err) { console.log(err); } reply(posts); }); }, validate: { query: { type: Joi.string().optional(), tags: Joi.string().optional() } } 

我的想法是validation应该允许任何typetags参数的子集(包括空查询)。 但是,在做出任何允许的请求后,我收到以下错误:

 { "statusCode": 400, "error": "Bad Request", "message": "value is not allowed", "validation": { "source": "query", "keys": [ "value" ] } } 

这是为什么? 当然没有关键的value 。 如何使validation按照我想要的方式运行?

如果您定义了一个非types的模式对象,Joi将其内部转换为object()types。 所以这个模式:

 var schema = { type: Joi.string().optional(), tags: Joi.string().optional() }; 

变为:

 var schema = Joi.object().keys({ type: Joi.string().optional(), tags: Joi.string().optional() }); 

因为您在服务器设置中将presence设置为forbidden ,所以将其应用于对象types,因此该模式变为:

 var schema = Joi.object().forbidden().keys({ type: Joi.string().optional(), tags: Joi.string().optional() }); 

正如你所看到的,它将主对象标记为被禁止,除了undefined之外,将不允许任何值:

 var Joi = require('joi'); var schema = Joi.object().forbidden().keys({ type: Joi.string().optional(), tags: Joi.string().optional() }); var value = {}; Joi.validate(value, schema, { presence: 'forbidden' }, function (err, value) { console.log(err); }); 

它输出:

 { [ValidationError: value is not allowed] name: 'ValidationError', details: [ { message: 'value is not allowed', path: 'value', type: 'any.unknown' } ], _object: {}, annotate: [Function] } 

所以你需要做的是标记主要的对象要么或optional覆盖forbidden

 validate: { query: Joi.object().required().keys({ type: Joi.string().optional(), tags: Joi.string().optional() }) }