如何在`res.send`之后但在响应离开服务器之前挂钩,==>当res.statusCode知道时

dio*_*ney 7 javascript middleware node.js express

我已经使用了中间件的设施Express.js借助app.use()挂钩上的所有请求,并记录信息,但发现的事实,res.statusCode几乎总是200,我检查是不正确的.我想这是默认值,因为它没有替代与我自己statusCoderes.send(204)好,始终是200.

我知道我可以res.send(x)在每次请求后记录消息,但正如您可能想象的那样,这很麻烦.

所以,问题是:

在哪里/如何将我的中间件功能与只在一个地方的条件挂钩并且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);
Run Code Online (Sandbox Code Playgroud)

如果我移动app.use(app.router)中间件,请不要执行.

Aar*_*our 16

res继承自http.ServerResponse 标准库.这意味着它EventEmitterfinish事件有关.因此,在您的中间件中,注册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();
});
Run Code Online (Sandbox Code Playgroud)

当然,您可以注册res.once,但finish事件保证只会触发一次,因此除非标准库中存在错误,否则不需要这样做.

这不一定会在res.send您提出请求之后"在响应离开服务器之前"发生- finish事件上的文档仅声明这一点

[T]当响应头和主体的最后一段被切换到操作系统以通过网络传输时,发出他的事件.

因此,一些响应可能已经离开了服务器.但是,我相信它是没有猴子修补的最接近的express,我建议反对.