Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validating JSON query string as query param using Joi

Tags:

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.

like image 683
Badr Avatar asked Mar 21 '16 08:03

Badr


1 Answers

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.

Hapi Version ≥18

You can set your custom parser via server.options.query.parser.

Hapi Version ≤17

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.

like image 170
Matt Harrison Avatar answered Nov 15 '22 07:11

Matt Harrison