【问题标题】:Get response status code in a middleware在中间件中获取响应状态码
【发布时间】:2018-06-27 09:01:18
【问题描述】:

我正在构建一个应用程序,我正在尝试为每个请求构建自己的日志记录系统。

对于每个请求,我想记录时间戳、使用的方法、路由,最后是发送给客户端的响应代码。

我目前有以下代码:

// index.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

const app = express();
app.use(bodyParser.json());
app.use(cors());

app.use(require('./lib/logging'));

app.get('/', (req, res, next) => {
  res.send('hello world !');
});

app.listen(3001);

// ./lib/logging.js
const moment = require('moment');
const chalk = require('chalk');
const log = console.log;

module.exports = (req, res, next) => {
  let now = `[${chalk.green(moment().format('HH:mm:ss'))}]`;
  let method = chalk.magenta(req.method);
  let route = chalk.blue(req.url);
  let code = chalk.yellow(res.statusCode); // Always 200
  log(`${now} ${method} request received on ${route} ${code}`);
  next();
}

不幸的是,即使我这样做res.status(201).send('hello world') 它总是会捕获200 状态码... 有没有办法捕获任何传给客户端的响应并获取其状态码?

【问题讨论】:

  • 中间件在哪里调用?
  • 在索引中,在声明路由`'/'之前。我尝试将中间件放在路由之后,但我认为这不是解决方案
  • 执行 res.send 后,您的中间件不会执行。使用以下问题的解决方案 - stackoverflow.com/questions/20175806/…
  • 有点跑题了,但我才意识到这对于 express 来说是多么的笨拙,而对于 Koa 来说是多么的容易。无论如何,我认为对于这个用例,您可能只需要挂钩 finish 事件而不是使用中间件。
  • 即使使用res.on('finish', () => {console.log(res) /* undefined */}),我仍然无法获得状态码

标签: javascript node.js express middleware http-status-codes


【解决方案1】:

使用响应中的finish 事件确实是一个很好的解决方案。问题出在finish事件回调中,我只是不能使用箭头函数,因为它不会绑定this关键字,这是存储响应数据的。

所以下面的代码是有效的:

// ./lib/logging.js

const moment = require('moment');
const chalk = require('chalk');
const log = console.log;

module.exports = (req, res, next) => {
  let now = `[${chalk.green(moment().format('HH:mm:ss'))}]`;
  let method = chalk.magenta(req.method);
  let route = chalk.blue(req.url);
  res.on('finish', function() {
    let code = chalk.yellow(this.statusCode);
    log(`${now} ${method} request received on ${route} with code ${code}`);
  })

  next();
}

【讨论】:

    【解决方案2】:

    Express 响应extends Node.js http.ServerResponse,因此您可以监听'finish' 事件:

    事件:“完成”

    在发送响应时发出。更具体地说,当响应头和正文的最后一段已移交给操作系统以通过网络传输时,将发出此事件。这并不意味着客户端已经收到任何东西。

    app.use((req, res, next) => {
      res.on('finish', () => {
        console.log(`Responded with status ${res.statusCode}`);
      });
      next();
    });
    

    【讨论】:

      【解决方案3】:

      创建中间件并覆盖发送函数

      app.use(function (req, res) {
          var send = res.send;
          res.send = function (body) {
              // Do something
              send.call(this, body);
          };
      });
      

      【讨论】:

        【解决方案4】:

        我的理解是您需要在响应中添加一些状态代码

        您可以像这样简单地设置状态代码

        let code = {
           serverError:500,
           forbidden:401
        }
        
        res.status(code.serverError).json({
          message:'Server error'
        })
        

        如果要在中间件中设置

        middleware.js

        const statuscode = function middleware(req,res,next){
        
        
            let code = {
               serverError:500,
               forbidden:401
            }
        
            req.statusCode =code.serverError
           next()
        
        }
        
        module.exports = {
          statuscode
        }
        

        index.js

        const middleware = require('./middleware');
        
        app.get('/',middleware.statuscode, (req, res, next) => {
          console.log("Code from middleware",req.statusCode);
          res.send('hello world !');
        });
        

        【讨论】:

        • 通过这样做,这意味着我必须将middleware.statuscode 放在每条路线中,这是我不想要的。我可以捕获每个请求,我不能捕获每个响应吗?
        • 将状态码放到配置文件中,在需要的地方使用
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-07
        • 2017-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多