我试图在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);
我会在OK
上调用/test/1
和middleware
时打印/test/2
以外的其他内容。
app.use("/test/", router2.use(middleware), router1);
但输出似乎是倒置的,相当于:
app.use("/test/", router2, middleware, router1);
我真正想要的是只有第一个使用中间件的路由器。 换句话说,将中间件用于第一个控制器。
我可以轻松交换router1
和router2
的顺序,但我的其他要求是因为我的router2
实际上使用了捕获所有请求的路由(/:id
)我需要持续下去。
我在这里失踪了什么,我怎么能做我想做的事?
我最想要的是这个:
/
|-test/
|-route // use middleware
|-something // use middleware
|-another // use middleware
...
|-:id // without middleware
这就是为什么我的路由器有很多路由在router1
下我需要中间件的地方。
而且router2
有一个没有中间件的全能。
答案 0 :(得分:1)
您可以在定义路线时设置中间件:
router1.get("/1", middleware, handler);
router2.get("/2", handler);
第一个将使用中间件,第二个不使用。
BTW我建议如下:不要为每条路线创建单独的路由器,只有一条就够了。
const router = express.Router();
router.get("/1", handler);
router.get("/2", handler);
app.use("/test/", router);
答案 1 :(得分:1)
当router1
和router2
绑定到一个公共路由时,它们将按顺序执行,连同它们的中间件,直到其中一个路由器路由与请求的路径/路由匹配。
在您的情况下,由于您无法交换路由器的顺序,您可以创建一个包装路由器的中间件,检查路由器中是否存在请求的路径/路由,如果是,则返回它,否则只是跳过它
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);