【问题标题】:Express.js - Access target route details in Application-level MiddlewareExpress.js - 在应用程序级中间件中访问目标路由详细信息
【发布时间】:2019-09-09 13:28:59
【问题描述】:

背景:

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

问题

在路由器级中间件中。我可以访问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不同

【问题讨论】:

    标签: javascript node.js express middleware


    【解决方案1】:

    我也遇到了这个问题。我在互联网上没有找到任何可以解决它的东西,所以我尝试搜索快递代码本身,以了解它为找到路线所做的工作。基本上它与下面的代码相同,它查找哪个正则表达式对该路由有效。 (谷歌翻译)

    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)
    

    【讨论】:

    • 这能回答问题吗?如果没有,请考虑将其作为评论而不是答案发布。
    • 对之前的评论感到抱歉,我将查看此解决方案,并将其设置为测试时的真实答案。我不再需要这种方法了,通过一些解决方法来做到这一点。如果这行得通,我会印象深刻。
    • 已确认。这不是一个真正的解决方案,而是一个很好的解决方法。当您在堆栈上循环时,可能会导致大型应用程序出现一些性能问题,regexp.exec 有时可能很昂贵。似乎没有直接的解决方案,我接受这个。
    • 这个解决方案确实是一个替代方案。只有当我开始研究 express 代码时,当你调用下一个函数时,它实际上执行相同的事情,改变它们直到你找到它。我也对性能产生了同样的担忧。为什么它真的不是一个很酷的解决方案。
    • 我最新的 API 是使用 NestJS 制作的,它在后台运行 express。我需要控制每条路线和行动。这是我能够做到的唯一方法。据我了解,这是您在问题中提出的建议。但是,对于更大的应用程序,我们应该考虑更多的东西。
    【解决方案2】:

    你希望 req.route 中有什么数据?

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

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

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

    【讨论】:

    • 为了您的问题,我添加了一些细节。你能读一下吗。顺便说一句,我不想​​在 req 中添加任何字段。
    • 为什么你需要得到这个:'/test/:someParams'?
    • 复杂。这将是我为一个项目编写的全局权限系统的一部分。这条路线将是系统的一小部分。 Like X 用户有权访问/test/:someParams。如果我使用req.originalUrl,这将更加复杂。 someParams 正在改变。
    【解决方案3】:

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

    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()
    })
    

    【讨论】:

    • 嗨,Ashok,我认为存在误解。我不想将任何内容附加到 req. req.route 是 express 的本机对象,可以在路由器级中间件中访问。但不是应用程序级中间件。你能再读一遍我的问题吗
    • @PeshrawH.Ahmed 您不能使用应用程序级中间件,您必须使用路由器级中间件,直到 express 版本 4.17.1(最新版本)。
    猜你喜欢
    • 2020-05-11
    • 2021-09-14
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    相关资源
    最近更新 更多