如何根据请求调用 middle-ware 并在 Node.js 中发送响应

How to call middle-ware on request and sending response in Node.js

我需要构建一个中间件来拦截请求并添加一些 headers。在发送响应之前,需要处理一些逻辑。我怎样才能做到这一点? 下面的一段代码只执行了一次。

    var express = require('express');
    var http = require('http');
    var app = express();
    app.use(function (req, res, next) {
        console.log(req.requestTime);
        if (!req.requestTime) {
            console.log("Setting!!!")
            req.requestTime = new Date();
            next();
        } else {
            var oldSend = res.send;
            res.send = function (data) {
                console.log("Tracker", res.status);
                console.log(req.requestTime);
                oldSend.apply(res, arguments);
            }
            next();
        }
    })
    const router = express.Router();
    router.get('/', (req, res) => {
        res.status(200).send();
    })

    app.use(router);
    var server = http.createServer(app);

    server.listen(3000);

我看到一个问题。每个请求都有一个新的 req 对象。所以,当一个新的请求进来时,你的中间件被调用并且没有 req.requestTime 所以代码进入 if 的第一个分支。代码永远不会进入 else 分支,因此你永远不会按照你想要的方式挂钩 res.send

我想你可能想要这个:

app.use(function (req, res, next) {
    if (!req.requestTime) {
        console.log("Setting!!!")
        req.requestTime = new Date();
        var oldSend = res.send;
        res.send = function (data) {
            console.log("Tracker", res.statusCode);
            console.log(req.requestTime);
            oldSend.apply(res, arguments);
        }
        next();
    }
});

而且,您甚至可能不需要 if (!req.requestTime),因为每个请求只调用一次此中间件,并且没有请求以 .requestTime 属性.[=21= 开头]

正如我在评论中所说,监听响应对象上的 finish 事件可能比仅 res.send() 猴子补丁更好,因为还有其他几个函数可以也发送回复。

app.use(function (req, res, next) {
    console.log("Setting!!!")
    req.requestTime = new Date();
    res.on('finish', () => {
        console.log("Tracker", res.statusCode);
        console.log(req.requestTime);
    });
    next();
});