我目前正在尝试使用这样的简单中间件功能记录每个Express请求的完整响应:
module.exports = (req, res, next) => {
const startTime = new Date();
const oldEnd = res.end;
res.end = (chunks, encoding) => {
const responseTime = new Date() - startTime;
res.set('Server-Timing', `total;dur=${responseTime}`);
console.log(req.path, `Response Time: ${responseTime}`);
res.end = oldEnd;
res.end(chunks, encoding);
};
next();
}
此代码在正常的Express终结点上可以正常工作,但是当我尝试为这样的静态文件提供服务时:app.use('/static/path', express.static('path'))
,出现以下错误:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
这是由于res.set
为服务器计时而发生的,但这意味着express.static
两次使用.end()
吗?当我在中间件函数中console.log
时,它只会被调用一次。
我正在使用NodeJS 10和Express 4.16.4
有人知道如何解决这个问题吗?
答案 0 :(得分:1)
res.end
不会被调用两次。
serve-static正在将文件流式传输到客户端,并且在文件的第一块写入流中时,将发送标头。从nodejs文档中:
如果在调用此方法之前调用response.write()或response.end(),则将计算隐式/可变头,并调用此函数。
因此,在流开始向客户端发送数据之后,无法设置标头。但是可以在服务静态选项中传递setHeader函数。
express.static('./public', {
setHeaders: (res, path, stat) => {
const responseTime = new Date() - res.locals.startTime;
res.set('Server-Timing', `total;dur=${responseTime}`);
},
});
但是,由于标题是在蒸汽开始时发出的,因此响应时间不准确。对于标头,更多的响应时间。