【问题标题】:middleware after all route in nodejsnodejs中的所有路由之后的中间件
【发布时间】:2017-06-20 08:21:54
【问题描述】:

我想要一个中间件,比如每条路由的 Express log request summary end =>

[POST] /books/commentpart 200 1435.472 ms - 35

我想在每个请求的末尾记录更多数据。但是我不知道如何编写这样的中间件。我在所有路由之后都尝试了中间件功能,但它没有用。在每个路由器中,我还通过 next() 调用。


app.use(responseTime());
//router
app

  .use(users(app, db))  
  .use(dataLogs(app, db))  
  .use(category(app, db));

//log middleware
app.use(function(req, res, next) {   
    var data = {};  
    var method = req.method;
    if(method == 'GET'){
      data = req.query;
    } else {
      data = req.body;
    }   
    var resTime = res.getHeader('X-Response-Time');    
    log.debug(' [ ' + iduser + ' ] - ' + req.route.path +  ' - ' + resTime + ' : ' + JSON.stringify(data));
});

module.exports = app;

【问题讨论】:

  • 您能分享一下您尝试过但没有奏效的方法吗?
  • 我添加了更多代码,谢谢
  • 我认为您应该能够使用morgan 实现类似的功能。

标签: node.js express middleware


【解决方案1】:

因此,中间件在注册时(使用app.useapp.all 等)是适用于传入请求的规则队列。请注意,此注册发生在服务器启动时,并且是服务器本身的一部分,而不是请求。

一旦全部设置完毕并且服务器正在运行,只有在前一跃点明确调用next() 时,才会调用第一个跃点之后的任何跃点(队列中的步骤,也称为中间件)。换句话说,如果你在所有中间件的开头加上一个app.use((req, res, next) => {});,服务器绝对不会做任何事情! -- 这个中间件只是吞下任何传入的请求,而不是调用next()

问题

现在的问题是,如何注册一个中间件:

  1. 适用于所有规则,并且
  2. 在所有其他中间件之后运行

满足第二个要求并不容易。因为正如我们上面提到的,这个规则队列中的最后一跳只有在所有先前的都优雅地依次调用next() 时才会运行。有时由于各种原因它不会发生,包括只是忘记打电话给next()!而且很难强制人们这样做。

解决方案

我需要提一下@robertklep 在上面加粗的评论中所说的话。它在res 上使用on-finishedhttps://github.com/jshttp/on-finished

例子:

// have this before all the other middlewares
app.use((req, res) => {
    console.log("I'll be the first line executed, almost ever!");
    onFinished(res, (err) => {
        console.log("and I'll be the last one, knowing response"
                    + " code which is already sent is: " + res.statusCode);
    });
};

这样做是在响应完成时实际监听(您也可以使用on-headers)。所以这是在 express 上完成工作的一个全新维度,与现有的中间件队列机制不同。请小心并享受! ;)

【讨论】:

    【解决方案2】:

    中间件只是一个函数,它做一些事情,然后使用“next()”将请求传递给下一个函数。因此,如果您真的想这样做,则需要在同一条路线中捕获所有路线,如下所示

    app.all('*', (req, res) => {
          // do something before
    
          // your async code here 
    
          // do something after
    });
    

    【讨论】:

    • 中间件只叫“进来”(收到请求时),不叫“出去”(发回响应时),所以如果logger依赖的数据依赖于响应(例如特定的响应标头),您需要使用 on-headerson-finished 之类的内容。
    • 这就是为什么我要演示的是,在你的控制器内部你需要将你的逻辑实现为中间件,然后再做一些事情
    【解决方案3】:

    终于成功了。实际上,在某些路由中,我忘记在每个路由器的末尾传递 next()。

    现在我使用另一种方法,利用 responseTime 函数,它可以完美地工作,而无需在所有路由中添加 next()。谢谢大家!

    app.use(responseTime(function (req, res, time) {
      var data = {};  
        var method = req.method;
        if(method == 'GET'){
          data = req.query;
        } else {
          data = req.body;
        }
       log.info(method, iduser, req.path, ' - ', Math.round(time), 'ms', ' : ', JSON.stringify(data));
    }))
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    相关资源
    最近更新 更多