解决 HTTP 在 Node.JS 中将标头发送到客户端后无法设置标头

在使用 express 和 Node.JS 时,我们有时会得到这个错误:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:277:15)
    at ServerResponse.setHeader (node:_http_outgoing:563:11)
    at ServerResponse.header (/node_modules/express/lib/response.js:771:10)
    at file:///link/to/file/app.js:309:13 {
    code: 'ERR_HTTP_HEADERS_SENT'
}

如果您不熟悉 HTTP 标头,这是一个非常令人困惑的错误。当您向用户或客户端发送超过 1 个响应时,会出现此错误。这意味着接收器得到两个响应,而它应该只得到一个。要解决此问题,请确保您只发送一个响应。

如何解决 ERR_HTTP_HEADERS_SENT 错误#

这通常是在您向客户端发送响应时引起的,然后一段异步代码在第一个响应之后发送了第二个响应。查看您的代码,您可能不小心使用res.send了两次。例如,以下将导致错误:

app.get('/app', async function(req, res) {
    /* Don't do this! Remove one of the res.send functions to remove the error */
    await User.find({username: req.headers.username}, function(err, items) {
        res.send('User');
    })
    res.send('Hello');
})

注意:其他 res 函数,比如res.redirect会导致同样的问题,即下面的代码也是错误的:

app.get('/app', function(req, res) {
    /* Don't do this! Remove one of these functions to remove the error */    
    await User.find({username: req.headers.username}, function(err, items) {
        res.redirect('/app/login');    
    })
    res.send('Hello');
})

您的代码应该看起来像这样,只有一个res功能:

app.get('/app', function(req, res) {
    res.redirect('/app/login');
})

防止发送多个标头#

如果您想防止在 Express 和 Node.JS 中确定地发送多个标头,请使用res.headersSent. 如果设置为 true,则标头已发送。

例如,以下代码将res.headerSent防止重新发送标头:

app.get('/app', function(req, res) {
    res.send('Hello');
    
    // Will not send, as we have already sent once.
    // Prevents error.
    if(res.headersSent !== true) {
        res.send('Hello');
    }
})