【发布时间】:2019-08-25 23:10:13
【问题描述】:
我正在使用 Node.js、Mongoose 和 Koa 开发一个 RESTful API,但对于架构和输入验证方面的最佳实践,我有些困惑。
目前,我对每个资源都有 Mongoose 和 Joi 模式。 Mongoose 模式仅包含有关特定资源的基本信息。示例:
const UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
},
firstName: String,
lastName: String,
phone: String,
city: String,
state: String,
country: String,
});
Joi 架构包含有关对象每个属性的详细信息:
{
email: Joi.string().email().required(),
firstName: Joi.string().min(2).max(50).required(),
lastName: Joi.string().min(2).max(50).required(),
phone: Joi.string().min(2).max(50).required(),
city: Joi.string().min(2).max(50).required(),
state: Joi.string().min(2).max(50).required(),
country: Joi.string().min(2).max(50).required(),
}
Mongoose 模式用于在写入数据库时在端点处理程序级别创建给定资源的新实例。
router.post('/', validate, routeHandler(async (ctx) => {
const userObj = new User(ctx.request.body);
const user = await userObj.save();
ctx.send(201, {
success: true,
user,
});
}));
Joi 模式在验证中间件中用于验证用户输入。每个资源我有 3 种不同的 Joi 模式,因为允许的输入因请求方法(POST、PUT、PATCH)而异。
async function validate(ctx, next) {
const user = ctx.request.body;
const { method } = ctx.request;
const schema = schemas[method];
const { error } = Joi.validate(user, schema);
if (error) {
ctx.send(400, {
success: false,
error: 'Bad request',
message: error.details[0].message,
});
} else {
await next();
}
}
我想知道我目前在 Mongoose 之上使用多个 Joi 模式的方法是否最佳,考虑到 Mongoose 也具有内置的 int 验证。如果没有,有哪些好的做法可以遵循?
谢谢!
【问题讨论】:
-
您能简要解释一下为什么要同时使用这两种方法吗?毕竟,Mongoose 模式非常强大,您可以在不使用 joi 的情况下对输入执行复杂的验证。
-
我考虑过将 Joi 验证作为请求级别的中间件,因为 Mongoose 似乎只在您创建/保存对象时提供应用级别的验证。
-
能否详细说明应用级和请求级的区别?
-
通过请求级别,我的意思是在收到请求时以及在执行其端点逻辑之前。这意味着如果输入没有通过验证中间件,请求可以立即终止。应用程序级别是指在执行端点逻辑时。因此,请求会通过所有中间件,并且当对象即将在数据库中更新时验证输入。
-
@omer 都是一样的。对吗?
标签: node.js rest mongoose koa joi