Hapijs and Joi: check request parameters with presence: 'forbidden'

My goal is to create an index route for messages. The user should be able to specify some query parameters (i.e. Tags, type), but should not specify others. To clarify:

This is normal:

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

This not normal:

 /posts?title=Hello 

This is the hapi pack configuration:

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

Pay attention to the presence: forbidden parameter.

This is the route 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() } } 

My idea was that validation should allow any subset of the type and tags parameters (including an empty request). However, after executing any of the allowed queries, I get the following error:

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

Why? Of course, there is no key named value . How to make the check correct the way I want it?

+5
source share
1 answer

If you define a non-type schema object, Joi converts it internally to the object() . So this diagram:

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

becomes:

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

Since you set the presence value to forbidden in the server settings, it applies to the type of the object, so the scheme becomes:

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

As you can see, it designates the main object as forbidden, which will not allow any value other than 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); }); 

It outputs:

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

So, you need to mark the main object either required or optional to override forbidden :

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

Source: https://habr.com/ru/post/1204094/


All Articles