使用 Joi 验证 JSON 查询字符串作为查询参数
Validating JSON query string as query param using Joi
我在 GET 请求查询参数中作为序列化字符串传递的验证问题 JSON。
我需要实现的是将这个序列化的字符串解析回 JSON 并使用 Joi 对其进行验证。
示例:给的是 JSON
{
limit: {size:10, page:0},
filter: {filter_by: 'foo', filter_val: 'foo', from: '1/1/2016',to: '1/1/2016' }
}
而这个JSON转换为查询字符串是:
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
我需要这样的东西来检查:
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(),
}
}
Joi 中有什么可以帮助解决这种情况,或者我需要为其编写自定义验证函数。
您需要换掉使用的查询字符串解析,因为默认情况下 hapi 不支持该格式。它只是使用 Node 内置的 url
模块来解析不支持查询字符串复杂编码的 URL。您需要使用 qs
手动解析它,之后您可以正常验证。
Hapi版本≥18
您可以通过 server.options.query.parser 设置自定义解析器。
Hapi版本≤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');
});
这是request.setUrl()
方法下的discussed a little bit in the API docs。
我在 GET 请求查询参数中作为序列化字符串传递的验证问题 JSON。
我需要实现的是将这个序列化的字符串解析回 JSON 并使用 Joi 对其进行验证。
示例:给的是 JSON
{
limit: {size:10, page:0},
filter: {filter_by: 'foo', filter_val: 'foo', from: '1/1/2016',to: '1/1/2016' }
}
而这个JSON转换为查询字符串是:
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
我需要这样的东西来检查:
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(),
}
}
Joi 中有什么可以帮助解决这种情况,或者我需要为其编写自定义验证函数。
您需要换掉使用的查询字符串解析,因为默认情况下 hapi 不支持该格式。它只是使用 Node 内置的 url
模块来解析不支持查询字符串复杂编码的 URL。您需要使用 qs
手动解析它,之后您可以正常验证。
Hapi版本≥18
您可以通过 server.options.query.parser 设置自定义解析器。
Hapi版本≤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');
});
这是request.setUrl()
方法下的discussed a little bit in the API docs。