要记录什么来调试错误 [ERR_HTTP_HEADERS_SENT]?

ab1*_*b11 1 node.js express

在 Express 控制器功能中,我遇到了此错误Error [ERR_HTTP_HEADERS_SENT]res.json()如果已在对象上设置标头,则当我调用时会发生这种情况res。但是,我在函数(或中间件)中没有看到可以在调用之前设置标头的位置res.json()

为了调试这个错误的原因,我想我可以添加一些日志记录。在调用 之前res.json,我可以检查标头是否已设置,如果是,则记录有关设置者的一些信息。

async function get(req, res) {

  ... 

  if (res._header) {
    logger.debug(...);
  }

  res.json(...);
Run Code Online (Sandbox Code Playgroud)

不幸的是,我在要记录的对象中没有看到任何有用的res信息,也没有看到任何表明为什么/如何设置标头(或谁设置了标头)的消息。对于我可以记录哪些内容来调试此问题有什么建议吗?或者其他调试建议?

Eri*_*ong 5

您可以修补res.header res.send res.set以记录堆栈跟踪。例如,这是我的主要应用程序。

const express = require('express');
const app = express();

const someGoody = require('./stupid-blackbox');

/** patch the res **/
app.use((req, res, next) => {
  const _header = res.header.bind(res); // .header and .set is an alias pair
  const _send = res.send.bind(res);

  res.header = res.set = (field, val) => {
    console.trace('.header/.set called', field, val);
    console.log('-----');
    return _header(field, val);
  }

  res.send = (body) => {
    console.trace('.send called', body);
    console.log('-----');
    return _send(body);
  }

  next();
})

// some innocent looking middleware
app.use(someGoody);

// my main routes
app.get('*', (req, res) => {
  res.json({url: req.url});
})

app.listen(3000);
Run Code Online (Sandbox Code Playgroud)

对于stupid-blackbox.js

const express = require('express');
const router = express.Router();

router.use((req, res, next) => {
  res.header('X-Crash-You', '1').send(':)');
  next();
})

module.exports = router;
Run Code Online (Sandbox Code Playgroud)

运行时,您将在日志中看到以下内容:

Trace: .header/.set called X-Crash-You 1
    at ServerResponse.res.header.res.set (C:\Users\eric_\Desktop\initial\play\index.js:11:13)
    at router.use (C:\Users\eric_\Desktop\initial\play\stupid-blackbox.js:6:9)
    at Layer.handle [as handle_request] (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:317:13)
    at C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:275:10)
    at Function.handle (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:174:3)
    at router (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:47:12)
    at Layer.handle [as handle_request] (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\layer.js:95:5)
-----
Trace: .send called :)
    at ServerResponse.res.send (C:\Users\eric_\Desktop\initial\play\index.js:17:13)
    at router.use (C:\Users\eric_\Desktop\initial\play\stupid-blackbox.js:6:36)
    at Layer.handle [as handle_request] (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:317:13)
    at C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:275:10)
    at Function.handle (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:174:3)
    at router (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\index.js:47:12)
    at Layer.handle [as handle_request] (C:\Users\eric_\Desktop\initial\play\node_modules\express\lib\router\layer.js:95:5)
Run Code Online (Sandbox Code Playgroud)

在每个堆栈跟踪的第二行,您可以看到愚蠢的blackbox.js。

顺便说一句,如果仅调用或,则res.json不会导致错误,错误是标头已发送,这意味着代码中的某处被调用,导致标头在实际代码之前发送。res.headerres.setres.send