我创建了一个REST api,并希望在调用控制器逻辑之前验证主体和参数。为了进行验证,我使用了 Joi (https://www.npmjs.com/package/joi)。
假设我有一条带有一个url参数和一些正文变量的路由。 params
对象包含此url参数,但Joi仍返回400
。详细信息是
“ userId”是必需的
我试图创建一个显示我的代码的简约示例。要重现该错误,请创建 app.js 文件
const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const cors = require('cors');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use('/users', require('./routes/users.js'));
app.listen(3000);
由于每个验证都失败,因此仅需要一条测试路径。使用以下内容创建 users.js
const express = require('express');
const router = express.Router();
const usersController = require('../controllers/users.js');
const usersControllerPolicy = require('../policies/users.js');
router.get('/:userId', usersControllerPolicy.getUserById, usersController.getUserById);
module.exports = router;
这个 users.js 控制器文件
exports.getUserById = async (req, res, next) => {
const { userId } = req.params;
return res.status(200).json("everything is fine");
};
在策略方面,我创建了 users.js 策略,该策略将所需的架构添加到了中间件
const joi = require('joi');
const schemaValidation = require('../middleware/schemaValidation.js');
module.exports = {
getUserById: (req, res, next) => {
schemaValidation({
params: {
userId: joi.string().guid().required()
},
body: {}
}, req, res, next);
}
}
然后通过我的 schemaValidation.js
验证架构const joi = require('joi');
module.exports = (schema, req, res, next) => {
const { error } = joi.validate(req, schema);
if (error)
return res.status(400).json("something went wrong");
next(); // execute the controller logic
}
如您所见,我传入了整个req
对象。我这样做是因为有时我必须验证身体和参数。 Joi找不到url参数userId
,因此我返回了状态码400。
如何解决中间件验证问题,以验证req
对象中的两个对象?
答案 0 :(得分:2)
实际上Joi可以访问<div class="section-header text-center">
<h2>Testing</h2>
</div>
并可以正确地对其进行验证,这就是原因:
userId
访问// replace this
const { error } = joi.validate(req, schema);
// by this
console.log(req.params.userId);
const { error } = joi.validate(req, schema);
console.log(error.toString());
时的控制台输出:
localhost:3000/users/10
并在参数中访问包含有效GUID的URL时,例如``:
10
ValidationError: child "params" fails because [child "userId" fails because ["userId" must be a valid GUID]]
因此,Joi可以访问所需的一切并按预期工作。
那为什么会出现错误400?
好吧,正如在控制台中所记录的,Joi无法通过ad3756ae-2661-4d8c-aeda-dd51deef5ea9
ValidationError: "_readableState" is not allowed. "readable" is not allowed. "_events" is not allowed. "_eventsCount" is not allowed. "_maxListeners" is not allowed. "socket" is not allowed. "connection" is not allowed. "httpVersionMajor" is not allowed. "httpVersionMinor" is not allowed. "httpVersion" is not allowed. "complete" is not allowed. "headers" is not allowed. "rawHeaders" is not allowed. "trailers" is not allowed. "rawTrailers" is not allowed. "aborted" is not allowed. "upgrade" is not allowed. "url" is not allowed. "method" is not allowed. "statusCode" is not allowed. "statusMessage" is not allowed. "client" is not allowed. "_consuming" is not allowed. "_dumped" is not allowed. "next" is not allowed. "baseUrl" is not allowed. "originalUrl" is not allowed. "_parsedUrl" is not allowed. "query" is not allowed. "res" is not allowed. "route" is not allowed
的验证。这是因为,默认情况下,Joi不接受对象中的未知参数。您可以使用req
更改此设置,即使包含未知参数,它也可以验证对象。
因此,在您的情况下,应将.unknown(true)
的代码替换为以下内容:
policies/users.js
现在,当您再次访问包含有效GUID的URL(例如http://localhost:3000/users/ad3756ae-2661-4d8c-aeda-dd51deef5ea9)时,一切都会按预期进行,并且服务器将发送const joi = require('joi');
const schemaValidation = require('../middleware/schemaValidation.js');
module.exports = {
getUserById: (req, res, next) => {
// properly defines a schema with optional parameters
const schema = joi.object({
params: joi.object({
userId: joi.string().guid().required()
}).unknown(true),
}).unknown(true);
schemaValidation(schema, req, res, next);
}
}
!