【问题标题】:ExpressJS 4 middleware problemsExpressJS 4 中间件问题
【发布时间】:2017-05-24 08:13:06
【问题描述】:

我正试图围绕 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/2 上调用/test/1middleware 时,我会打印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 没有中间件的包罗万象。

【问题讨论】:

  • 好的,我知道为什么app.use("/test/", router2.use(middleware), router1); 似乎被颠倒了。我希望中间件能够包装我的所有路由,但它会将其作为层添加到最后一个位置。

标签: javascript node.js express router middleware


【解决方案1】:

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

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

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

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

const router = express.Router();

router.get("/1", handler);
router.get("/2", handler);

app.use("/test/", router);

【讨论】:

【解决方案2】:

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

在您的情况下,由于您无法交换路由器的顺序,您可以创建一个包装路由器的中间件,检查请求的路径/路由是否存在于路由器中,如果存在,则返回它,否则跳过它。

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-15
    • 2013-09-23
    • 1970-01-01
    • 2011-10-06
    • 2021-04-13
    • 2020-08-19
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多