Joi中如何根据请求头值动态验证请求体Payload?
基于请求头动态切换Joi验证规则的实现方案
以下是几种可行的实现方式,适配不同场景需求:
1. 利用Joi内置when()条件语法
直接在Schema中通过when()关联请求头字段,根据不同值动态应用验证规则。需要将请求头作为验证上下文传入Joi。
示例代码:
const Joi = require('joi'); const express = require('express'); const app = express(); app.use(express.json()); // 定义基础Schema及动态规则 const dynamicSchema = Joi.object({ commonField: Joi.string().required(), conditionalField: Joi.when(Joi.ref('$headers.x-some-key'), { is: 'value1', then: Joi.number().min(10).required(), otherwise: Joi.when(Joi.ref('$headers.x-some-key'), { is: 'value2', then: Joi.string().email().required(), otherwise: Joi.any().forbidden() }) }) }); app.post('/api/endpoint', (req, res) => { // 将请求头作为上下文传入验证 const { error, value } = dynamicSchema.validate(req.body, { context: { headers: req.headers } }); if (error) { return res.status(400).send(error.details[0].message); } res.send('Validation passed'); });
2. 自定义验证函数(custom())
通过Joi的custom()方法编写自定义逻辑,手动判断请求头值并执行对应验证,适合复杂的动态规则场景。
示例代码:
const Joi = require('joi'); const express = require('express'); const app = express(); app.use(express.json()); // 自定义验证逻辑 const validateConditionalField = (value, helpers) => { const xSomeKey = helpers.prefs.context.headers['x-some-key']; if (xSomeKey === 'value1') { const numSchema = Joi.number().min(10).required(); const { error } = numSchema.validate(value); if (error) return helpers.error('any.invalid'); } else if (xSomeKey === 'value2') { const emailSchema = Joi.string().email().required(); const { error } = emailSchema.validate(value); if (error) return helpers.error('any.invalid'); } else { return helpers.error('any.forbidden'); } return value; }; const dynamicSchema = Joi.object({ commonField: Joi.string().required(), conditionalField: Joi.any().custom(validateConditionalField).required() }); app.post('/api/endpoint', (req, res) => { const { error } = dynamicSchema.validate(req.body, { context: { headers: req.headers } }); if (error) { return res.status(400).send(error.details[0].message); } res.send('Validation passed'); });
3. 路由层面动态选择Schema
提前定义好对应不同请求头值的独立Schema,在路由处理前根据请求头选择对应的Schema进行验证,逻辑更直观,适合规则差异较大的场景。
示例代码:
const Joi = require('joi'); const express = require('express'); const app = express(); app.use(express.json()); // 预定义不同场景的Schema const schemaForValue1 = Joi.object({ commonField: Joi.string().required(), conditionalField: Joi.number().min(10).required() }); const schemaForValue2 = Joi.object({ commonField: Joi.string().required(), conditionalField: Joi.string().email().required() }); const defaultSchema = Joi.object({ commonField: Joi.string().required(), conditionalField: Joi.any().forbidden() }); // 动态选择Schema的中间件 const getDynamicSchema = (req, res, next) => { const xSomeKey = req.headers['x-some-key']; let schema; switch(xSomeKey) { case 'value1': schema = schemaForValue1; break; case 'value2': schema = schemaForValue2; break; default: schema = defaultSchema; } const { error } = schema.validate(req.body); if (error) { return res.status(400).send(error.details[0].message); } next(); }; app.post('/api/endpoint', getDynamicSchema, (req, res) => { res.send('Validation passed'); });
内容的提问来源于stack exchange,提问作者Roshan Birwatkar
相关产品推荐
相关产品推荐

