路由执行后,在中间件中使用更新的req变量

时间:2019-08-03 16:24:20

标签: express

我编写了一个中间件函数,用于对每个传入的HTTP请求执行一些日志记录

export const winstonMiddlewareLogger = (req: express.Request, res: express.Response, next: express.NextFunction) => {
    let _startTime = new Date();
    res.on("finish", function() {
        let responseTime = new Date().getTime() - _startTime.getTime() + "ms";
        let method = req.method;
        let url = req.originalUrl;
        let body = req.body ? req.body : {};
        let query = req.query;
        let params = req.params;
        let status = res.statusCode;
        let msg = `HTTP ${req.method} ${req.url} ${responseTime}`;
        let logDocument = {
            msg,
            method,
            url,
            params,
            query,
            body,
            status,
            responseTime,
        };
        logger.info(undefined, logDocument)
    });
    next();
};

我接下来要走的路线

app.post("/slow", (req, res) => {
    req.testParam = "test";
    res.send("hello");
});

我希望能够访问req事件监听器中的/slowtestParam)中初始化的res.on(...){...}参数的新属性。中间件功能的另一种方式:

if (req.hasOwnProperty('testParam')) {
       console.log(req.testParam)
   }

但是当前状态是无论我在路由本身中做什么,req参数都不会更新,因为它知道的req参数只是我在每个参数开头得到的参数请求。 在路由中更改req变量不会在已经拥有自己的req变量的中间件中对其进行更改。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

好吧,所以我发现winston-express实际上可以完成我想做的事情。 它的作用是将res.end函数重新分配给他自己编写的函数。 路由已执行后,此函数可以访问reqres的修改对象。

因此,为了展示其工作原理,我将路线更改为:

app.get("/", (req, res) => {
    req._attributeFromRoute = "test";
    res.send("hello");
});

我的中间件功能看起来像这样:

export const winstonMiddlewareLogger2 = (req: express.Request, res: express.Response, next: express.NextFunction) => {
    let _startTime = new Date();
    let end = res.end;
    res.end = (chunk: any, encoding: string, cb?: () => void): void => {
        res.end = end;
        res.end(chunk, encoding, cb);

        console.log(req._attributeFromRoute)  // Notice that this property was not declared before the route execution, and now we can access it after it was defined

        let responseTime = new Date().getTime() - _startTime.getTime() + "ms";
        let method = req.method;
        let url = req.originalUrl;
        let body = req.body ? req.body : {};
        let query = req.query;
        let params = req.params;
        let status = res.statusCode;
        let msg = `HTTP ${req.method} ${req.url} ${responseTime}`;
        let logDocument = {
            msg,
            method,
            url,
            params,
            query,
            body,
            status,
            responseTime,
        };
        logger.info(undefined, logDocument)
    };
    next();
};

它的工作方式是中间件函数将等待路由执行并调用req.end函数,该函数将进入我们自己创建的end函数。 然后,我们将执行原始end函数,该函数已在end变量中用作参考。 然后,我们可以对reqres的更新对象进行任何操作。