Express.js - 在应用层中间件中访问目标路由细节

Express.js - Access target route details in Application-level Middleware

背景:

我有一个带有一些简单路由和路由器级中间件的快速应用程序。我想注册一个应用级中间件。

问题

在路由器级中间件中。我可以访问 req.route 对象。但是我无法访问应用程序级中间件内的同一个对象。 我能理解这一点,因为在应用程序级中间件内部,程序还不在路由内。

但是有没有办法在全局中间件中获取 req.route 对象或等同于 req.route.path 的对象?

req.pathreq.originalUrl 包含真正的 url 而不是路由路径。

例子

const express = require('express');
const app = express();
const port = 3232;
app.use((req, res, next) => {
    const route = req.route; // It is an application level middleware, route is null
    return next(); 
});
app.get('/test/:someParams', (req, res) => {
    const route = req.route; // can access req.route here because it is a Router-level middleware

    console.log(route.path)
    console.log(req.path)
    return res.send('test')
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

输出

请求:GET@localhost:3232/test/33333

/test/33333 // I don't need this.
/test/:someParams // This is what I want to get inside the Application-Level Middleware 

备选方案

此问题的替代解决方案如下

const express = require('express');
const app = express();
const port = 3232;

function globalMiddleware(req, res, next) {
    const route = req.route;
    console.log(route) // can access it
    return next();
}

app.use((req, res, next) => {
    const route = req.route; // It is an application level middleware, route is null

    return next();
});
app.get('/test/:someParams', globalMiddleware, (req, res) => {
    const route = req.route; // can access req.route here because it is a Router-level middleware
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

但是,将相同的中间件注入我的每条和所有路由听起来并不是一个明智的解决方案。特别是在更大的应用程序上。

路由器对象转储

{ 
   "path":"/test/:someParams",
   "stack":[ 
      { 
         "name":"globalMiddleware",
         "keys":[ 

         ],
         "regexp":{ 
            "fast_star":false,
            "fast_slash":false
         },
         "method":"get"
      },
      { 
         "name":"<anonymous>",
         "keys":[ 

         ],
         "regexp":{ 
            "fast_star":false,
            "fast_slash":false
         },
         "method":"get"
      }
   ],
   "methods":{ 
      "get":true
   }
}

path 键是我想要得到的东西。请注意 req.route.pathreq.path

不同

您可以根据要求使用中间件

const middleware = (req, res, next) => {
    // Append what you want in req variable
    req.route = "abc"  // let abc
    req.path =  "path" // req.route.path
    next();
}

你可以从中间件这里得到它

app.get('/test/:someParams', middleware, (req, res) => {
    console.log(req.params.someParams)
    console.log(req.route) // "abc"
    console.log(req.path)  // "path"
});

对于应用层中间件

app.use((req, res, next) => {
   req.route = "abc"  // let abc
   req.path = "path" // or req.route.path
   next()
})

您希望 req.route 中的数据是什么?

您可以使用 req.urlreq.methodreq.originalUrl 等...

或者在应用程序级中间件中,您可以将新字段添加到 req 对象

req.customRoute = {yourField: "yourValue"} 该字段将在路由级中间件中可用

我也遇到了这个问题。我在互联网上没有找到任何可以解决它的东西,所以我试图搜索快递代码本身,看看它是如何找到路线的。基本上它与下面的代码是一样的,它查找哪个正则表达式对该路由有效。 (Google 翻译)

const url = req.originalUrl.split('?')[0] // Routes with query
const layer = req.app._router.stack.find(layer => {
  return layer.regexp.exec(url) && layer.route
})

所以可以访问原路径:

console.log(layer.route.path)