我已经通过app.use() Express.js 中使用了中间件工具来挂接所有请求并记录一条消息,但是发现res.statusCode几乎总是 200 ,这一事实我检查过是不正确的。我认为这是默认值,由于尚未用statusCode很好地替换为我自己的res.send(204),因此始终为 200

我知道我可以在每个请求中的每个res.send(x)之后记录该消息,但是正如您可能想像的那样,这很麻烦。

因此,问题是:

在哪里/如何将我的中间件功能与只在一个位置的条件 Hook ,而res.statusCode是客户端真正看到的条件?

相关代码:

// Log API requests.
app.use(function (req, res, next) {
    logger.info('API request.', {
        module: 'core'
        data  : {
            req: {
                method: req.method,
                url   : req.url,
                ip    : req.ip
            },
            res: {
                status_code: res.statusCode // Always 200 and not the really one.
            }
        }
    });

    next();
});

app.use(app.router);

如果我移动app.use(app.router),则不会执行中间件。

最佳答案

res继承自http.ServerResponse in the standard library。这意味着它是一个带有EventEmitter事件的finish。因此,在您的中间件中,注册finish事件并在该事件触发时进行日志记录:

app.use(function (req, res, next) {
    res.on('finish', function() {
        logger.info('API request.', {
            module: 'core'
            data  : {
                req: {
                    method: req.method,
                    url   : req.url,
                    ip    : req.ip
                },
                res: {
                    status_code: res.statusCode
                }
            }
        });
    });

    next();
});

当然,您可以向res.once注册,但是finish事件只能触发一次,因此除非标准库中存在错误,否则不必这样做。

这不一定会按照您的要求在“res.send之后但响应离开服务器之前”发生-finish事件上的文档仅声明



因此,某些响应可能已经离开服务器。但是,我相信,这是没有猴子补丁express所能获得的最接近的结果,对此我建议不要这样做。

09-06 11:14