使用express.static时Express自定义日志崩溃

时间:2018-12-21 09:14:45

标签: node.js express static

我目前正在尝试使用这样的简单中间件功能记录每个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

有人知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

res.end不会被调用两次。

serve-static正在将文件流式传输到客户端,并且在文件的第一块写入流中时,将发送标头。从nodejs文档中:

  

response.writeHead

     

如果在调用此方法之前调用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}`);
  },
});

但是,由于标题是在蒸汽开始时发出的,因此响应时间不准确。对于标头,更多的响应时间。