ExpressJS 4中间件问题

我试图用ExpressJS 4把我的头围绕在中间件上。

如果我正确理解的是,中间件是按照声明的顺序来应用的,你可以在不同的层次上“绑定”它们。

在这里,我试图在路由器级绑定一个中间件。

function middleware(req, res, next) { console.log("middleware"); res.write("middleware"); next(); } function handler(req, res) { console.log("OK"); res.status(200).send('OK'); } const router1 = express.Router(); const router2 = express.Router(); router1.get("/1", handler); router2.get("/2", handler); 

除了在/test/1/test/2上调用/test/1时打印OK

 app.use("/test/", router2.use(middleware), router1); 

但是输出似乎是倒置的,相当于:

 app.use("/test/", router2, middleware, router1); 

我真正想要的只是第一台使用中间件的路由器。 换句话说,将中间件用于第一个控制器。

我可以很容易地交换router1router2的顺序,但是我的其他要求是因为我的router2实际上使用了一个能够捕获所有请求( /:id )的路由,我需要最后一个。

我在这里错过了什么,我该怎么做我想要的?

编辑澄清:

我最终想要的是这样的东西:

 / |-test/ |-route // use middleware |-something // use middleware |-another // use middleware ... |-:id // without middleware 

这就是为什么我有一个路由器有许多路由在我想要的中间件router1 。 而router2与一个没有中间件的catch-all。

定义路由时可以设置一个中间件:

 router1.get("/1", middleware, handler); router2.get("/2", handler); 

第一个将使用中间件,第二个不使用。

顺便说一句,我会build议如下:不要为每个路由创build单独的路由器,只有一个就足够了。

 const router = express.Router(); router.get("/1", handler); router.get("/2", handler); app.use("/test/", router); 

由于router1router2绑定到一个公共路由,它们将按顺序执行,以及它们的中间件,直到其中一个路由器与请求的path/路由匹配。

在你的情况下,因为你不能交换路由器的顺序,你可以创build一个包裹路由器的中间件,检查路由器中是否存在请求的path/路由,如果是的话,返回它,否则就跳过它。

 var unlessMatch = function(router) { let routerPaths = []; // Retrieve, create a regex and store every route of the Router router.stack.forEach(layer => { if (layer.route) { routerPaths.push(layer.route.path.replace(/\/?(:[^\/]+)(\/?)/g, "/[^\/]+")); } }); return function(req, res, next) { // Check if requested route exists in the router routerPaths.every(path => { return new RegExp('^' + path + '(\/)?$').test(req.path) ? router(req, res, next) : true; }); return next(); }; }; function middleware(req, res, next) { console.log("middleware"); next(); } function handler(req, res) { console.log("OK"); res.status(200).send('OK'); } const router1 = express.Router(); const router2 = express.Router(); // Bind middleware to router2 router2.use(middleware); router1.get("/1", handler); router2.get("/2", handler); // Wrap router2 into unlessMatch middleware/function so that router2's middlewares // are not executed if no route matches with the requested one app.use("/test/", unlessMatch(router2), router1);