假设我的API POST /api/comments
中有一个POST请求,在其中创建注释。注释以数组树结构形式接收(每个注释都具有子属性,该属性可以具有子注释)。发送响应之前,我发生了多个“事件”。
我可以将所有所需的代码放入一个这样的中间件函数中。
function postComments(req, res, next) {
// handle general authentication
if (!isAuthenticated()) {
next("not authenticated ...");
}
// handle more specific authentication (ex. admin)
if (!isAdmin()) {
next("not admin ...")
}
// validate req.body.comments so that each comment has allowed form
if (!areCommentsValid()) {
next("not valid ...");
}
// modify comments for database insertion
const modifiedComments = modifyComments();
// database insertion
db.insert(modifiedComments)
res.sendStatus(201);
}
在上面的示例中,可以在多个路由中使用常规auth和admin身份验证,并且下一个中间件不依赖它们,代码仍在工作。因此,编写这2条代码是有意义的。
在这个例子中,我的中间件做了很多事情。
我以为我可以做的就是将以下代码拆分为多个中间件。
function userAuth(req, res, next) {
// handle user authentication
}
function adminAuth(req, res, next) {
// handle admin auth
}
function validateComments(req, res, next) {
// handle req.body.comments validation
}
function modifyComments(req, res, next) {
// modify comments
// req.commentsForDb = modifiedComments;
}
function postComments(req, res, next) {
// insert req.commentsForDb into database
}
所以现在我将中间件分成4个不同的中间件,但是问题是中间件相互依赖。
postComments
要求modifyComments
设置req.commentsForDb
,modifyComments
要求validateComments
等。哪种方法更好?
最佳答案
这是完全有效的,并且实际上是打算使用中间件的方式。
只要您在中间件出现问题时正确地用错误代码调用next,您就应该停止转发到下一个中间件。
此处的附加价值在于您可以在许多不同的路径中重用中间件。您可以做的另一件事是中间件关闭生成器,例如基于角色的auth中间件:
function auth(role) {
return function(req, res, next) {
// get my user
// ...
// check user role
if user.role != role {
return next(new Error("Auth failed"))
}
return next()
}
}
// this route is for admins
app.get(
"/foo",
auth("admin"),
foo
)
// this one for users
app.get(
"/bar",
auth("user"),
foo
)