【问题标题】:Execute middleware on every route call在每个路由调用上执行中间件
【发布时间】:2022-01-14 12:22:25
【问题描述】:

在我的 Express 应用程序中,我在 routes.ts 中实现路由:

    var Router = express.Router();

    Router.route('/models/:modelId')
      .get(function (req, res) {
          service.setParameter(req)
          service.get(req,res)
    });
 
     Router.route('/models/:modelId')
      .post(function (req, res) {
          service.setParameter(req)
          service.post(req,res)
    });

还有express.ts:

    export const App = express()

    App.use(express.json())
    App.use(express.urlencoded({ extended: true }))
    App.use(helmet())

    App.use('/', Router)

在每个路由器调用中,我想执行一段代码 service.setParameter(req),它从“params”获取特定参数,但我不想显式添加到每个路由器方法。

我尝试在路由器前后添加它作为中间件

    App.use('/', Router)

    App.use(function(req, res, next){
      service.setParameter(req)
      next()
    })

但是如果我在Router之前定义了,那么路由还没有设置,我没有得到我想要的参数,如果我在之后定义了,那么中间件就不会被执行。

如何以通用方式执行 service.setParameter(req) 以使其适用于所有路由?

【问题讨论】:

    标签: javascript node.js typescript express


    【解决方案1】:

    express.ts 文件中,您可以添加一个中间件,在安装路由器之前执行此操作,然后使用next() 继续前进。你可以这样做:

    App.use('/*', (req, res, next) => {
      service.setParameter(req);
      next();
    });
    
    App.use('/', Router)
    

    【讨论】:

      【解决方案2】:

      您需要将您的自定义中间件放在上下文路径和您的路由器之间app.use(..)

      const router = express.Router();
      router.post('/', (req, res) => {
          service.post(req,res);
      });
      
      router.get('/', (req, res) => {
          service.get(req,res)
      });
      
      app.use('/models', (req, res, next) => {
          service.setParameter(req);
          next();
      }, router);
      

      使用上面的代码,中间件将对'/models'的所有请求执行。

      【讨论】:

      • 谢谢@eol。 req.params 是否有望在中间件中可用?它对我来说是“未定义的”。
      • 您确定要查找req.params 而不是req.queryreq.params 代表路径参数,而不是您作为查询字符串传入的参数。如果您尝试匹配路径参数,则需要在上下文路径中指定它们,例如app.use('/models/:someId', ...)
      • 是的,我正在寻找路径参数。我更新了我的 OP 以反映我的结构 - 路由器位于不同的文件中,这可能是问题的原因,因为应用程序和路由器之间存在断开连接,路由器无法获取对应用程序的引用。
      • 好的,你有没有从评论中尝试过我的解决方案,即app.use('/models/:modelId', ...)
      • 是的,这就是我所做的pastebin.com/bhDbDUYN,但是当我执行那个端点时我得到了 404
      【解决方案3】:

      你可以使用app.use(async (req,res,next) => {...})来声明一个在所有请求中执行的中间件,如果你想首先调用这个中间件,它必须在你的路由之前声明,中间件必须调用next()为了继续执行流程,如果您想在请求结束时被调用,您必须在声明的末尾但在错误中间件之前,在这种方法中,每个路由都必须调用 next() at函数结束。

      第一种方法

      const express = require('express');
      const app = express();
      const router = express.Router();
      router.post('/', async (req, res) => {
          await service.post(req,res);
      });
      
      router.get('/', async (req, res) => {
          await service.get(req,res)
      });
      
      app.use((req,res,next) => {
         console.log("always called");
         next();
      });
      app.use('/',router);
      

      第二种方法

      const express = require('express');
      const app = express();
      const router = express.Router();
      router.post('/', async (req, res, next) => {
          await service.post(req,res);
          next();
      });
      
      router.get('/', async (req, res, next) => {
          await service.get(req,res);
          next();
      });
      
      app.use('/',router);
      app.use((req,res) => {
         console.log("always called");
      });
      

      【讨论】:

        【解决方案4】:

        感谢所有答案,他们帮助我更好地了解路由在 Express 上的工作原理。

        我找到了另一种解决方案,我认为在我的情况下效果最好 - 使用 Router.all() 方法:

        const setRequest = function(req, res, next){
          logger.setRequest(request)
          next()
        }
        
        Router.route('/models/:model_id')
        .all(setRequest)
        .get(function (req, res) {service.execute()})
        .put(function (req, res) {service.execute()})
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-20
          • 2015-10-20
          • 2018-11-28
          • 1970-01-01
          • 2016-12-16
          • 2020-01-20
          相关资源
          最近更新 更多