我编写了一个中间件函数,用于对每个传入的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
事件监听器中的/slow
(testParam
)中初始化的res.on(...){...}
参数的新属性。中间件功能的另一种方式:
if (req.hasOwnProperty('testParam')) {
console.log(req.testParam)
}
但是当前状态是无论我在路由本身中做什么,req
参数都不会更新,因为它知道的req
参数只是我在每个参数开头得到的参数请求。
在路由中更改req
变量不会在已经拥有自己的req
变量的中间件中对其进行更改。
有什么想法吗?
答案 0 :(得分:0)
好吧,所以我发现winston-express实际上可以完成我想做的事情。
它的作用是将res.end
函数重新分配给他自己编写的函数。
路由已执行后,此函数可以访问req
和res
的修改对象。
因此,为了展示其工作原理,我将路线更改为:
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
变量中用作参考。
然后,我们可以对req
和res
的更新对象进行任何操作。