Express.js中间件可以依赖链中以前的中间件吗?

时间:2019-03-25 04:58:22

标签: javascript node.js express

假设我在我的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.commentsForDbmodifyComments要求validateComments等等。

哪种方法是首选?

1 个答案:

答案 0 :(得分:2)

这是完全有效的,并且实际上是打算使用中间件的方式。 只要您在中间件出现问题时正确地用错误代码调用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
)