Reputation: 10648
I have a problem of validation JSON that is passed in GET request query param as a serialized string.
What I need to achieve is to parse this serialized string back to JSON and validated it using Joi.
Example: Give is the JSON
{
limit: {size:10, page:0},
filter: {filter_by: 'foo', filter_val: 'foo', from: '1/1/2016',to: '1/1/2016' }
}
And this JSON is converted to query string is:
limit%5Bsize%5D=10&limit%5Bpage%5D=0&filter%5Bfilter_by%5D=foo&filter%5Bfilter_val%5D=foo&filter%5Bfrom%5D=1%2F1%2F2016&filter%5Bto%5D=1%2F1%2F2016
I need something like this to check:
validate: {
query: {
limit: Joi.someMethodToGetJsonFromString.object().keys({
size: Joi.number(),
page: Joi.number()
}
filter: Joi.someMethodToGetJsonFromString,.object().keys({
filter_by: Joi.string().valid(['option1', 'option2']),
filter_val: Joi.string(),
from: Joi.date(),
to: Joi.date(),
}
}
Is there anything in Joi that can help in this scenario, Or I need to write custom validation functions for it.
Upvotes: 5
Views: 6429
Reputation: 13567
You'll want to swap out the query string parsing used because hapi doesn't support that format by default. It just uses Node's built in url
module to parse the URL which doesn't support complex encodings of query strings. You'll need to manually parse it using qs
, after that you can validate as normal.
You can set your custom parser via server.options.query.parser.
const Hapi = require('hapi');
const Joi = require('joi');
const Url = require('url');
const Qs = require('qs');
const server = new Hapi.Server();
server.connection({ port: 4000 });
const onRequest = function (request, reply) {
const uri = request.raw.req.url;
const parsed = Url.parse(uri, false); // skip the querystring parsing
parsed.query = Qs.parse(parsed.query); // parse it ourselves with qs
request.setUrl(parsed);
return reply.continue();
};
server.ext('onRequest', onRequest);
server.route({
config: {
validate: {
query: {
limit: Joi.object().keys({
size: Joi.number(),
page: Joi.number()
}),
filter: Joi.object().keys({
filter_by: Joi.string().valid(['option1', 'option2']),
filter_val: Joi.string(),
from: Joi.date(),
to: Joi.date(),
})
}
}
},
method: 'GET',
path: '/',
handler: function (request, reply) {
return reply('ok');
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Started server');
});
This is discussed a little bit in the API docs under the request.setUrl()
method.
Upvotes: 4