【问题标题】:Can't set headers after they are sent nodejs发送后无法设置标头nodejs
【发布时间】:2018-11-21 09:48:37
【问题描述】:

我创建了一个常见的错误处理中间件来处理应用程序中的所有错误。 但是当我运行我的 api 时它会显示一些错误,例如“错误:发送后无法设置标题。” 我通过使用未定义的错误“a”手动引发错误,例如 res.json("testing"+a);

错误:

Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:491:11)
    at ServerResponse.setHeader (_http_outgoing.js:498:3)
    at ServerResponse.header (D:\nodejs\synchronizer\node_modules\express\lib\response.js:767:10)
    at ServerResponse.send (D:\nodejs\synchronizer\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (D:\nodejs\synchronizer\node_modules\express\lib\response.js:267:15)
    at process.on (D:\nodejs\synchronizer\middlewares\logging.js:31:21)
    at emitTwo (events.js:131:20)
    at process.emit (events.js:214:7)
    at emitPendingUnhandledRejections (internal/process/promises.js:108:22)
    at runMicrotasksCallback (internal/process/next_tick.js:124:9)
[nodemon] app crashed - waiting for file changes before starting...

server.js

const express = require('express');
const log = require('../middlewares/logging');
module.exports = function(app){
    // default options
    app.use(fileUpload());

    //it is required for form submit for post method
    app.use(express.json());
    const bodyParser = require("body-parser");

    /** bodyParser.urlencoded(options)
     * Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
     * and exposes the resulting object (containing the keys and values) on req.body
     */

    // for parsing application/json
    app.use(bodyParser.json()); 
    app.use(bodyParser.text());
    // for parsing application/xwww-
    app.use(bodyParser.urlencoded({ extended: true })); 
    //form-urlencoded

    // for parsing multipart/form-data
    //app.use(upload.array()); 

    //this is middleware is responsible to serve websites static contents of public folder
    app.use(express.static('public'));

    //Every Request Response Logging Middleware
    app.use(log);

    app.get('/test', async (req, res) => {
        res.json("testing"+a);
    });
}

logging.js

const winston = require('winston');

var getLabel = function (callingModule) {
  var parts = callingModule.filename.split('/');
  return parts[parts.length - 2] + '/' + parts.pop();
};

module.exports = function(req, res, next) {
  const logger = winston.createLogger({
    levels: winston.config.syslog.levels,
    transports: [
      new winston.transports.File({
        filename: 'Logs/combined.log',
        level: 'info'
      })
    ],
    exitOnError: false
  });

  var logmsg = {
    'Request IP':req.ip,
    'Method':req.method,
    'URL':req.originalUrl,
    'statusCode':res.statusCode,
    'headers':req.headers,
    'Time':new Date()
  };

  process.on('unhandledRejection', (reason, p) => {
    logger.error('exception:'+reason);
    //below line causes an error
    res.status(200).json({
        'statuscode': 200,
        'message': 'Validation Error',
        'responsedata': 'Unhandled Exception Occured'
    });  
  });
  logger.log('info', logmsg);
  next();
}

【问题讨论】:

  • 我认为您发送的是res.status(200).json [...],那么您发送的是/test 响应不是吗?请尝试设置一些 console.log() 以查看完整的执行堆栈
  • 如果我删除 res.status(200).json({ 'statuscode': 200, 'message': 'Validation Error', 'responsedata': 'Unhandled Exception Occured' });那么我如何打印一个错误来响应呢?
  • 您可以检查res._headerSent 以查看响应是否已发送。

标签: node.js


【解决方案1】:

您正在为每个请求创建一个新的记录器,并为unhandledRejection 添加一个新的处理程序。

相反,创建一个记录器和一个处理程序。例如:

const winston = require('winston');

// one (module-wide) logger
const logger = winston.createLogger({
  levels: winston.config.syslog.levels,
  transports: [
    new winston.transports.File({
      filename: 'Logs/combined.log',
      level: 'info'
    })
  ],
  exitOnError: false
});

// one (app-wide) handler
process.on('unhandledRejection', (reason, p) => {
  logger.error('exception:'+reason);
});

// the logging middleware
module.exports = function(req, res, next) {
  const logmsg = {
    'Request IP':req.ip,
    'Method':req.method,
    'URL':req.originalUrl,
    'statusCode':res.statusCode,
    'headers':req.headers,
    'Time':new Date()
  };
  logger.log('info', logmsg);
  next();
}

如果您想处理请求/响应周期中发生的错误,请添加a proper error handler

【讨论】:

  • 请求部分工作正常,但如果我为错误创建另一个中间件,那么它就不能工作
  • 错误不会被记录,甚至输出也不会显示,如果我使用错误处理中间件
  • 是否调用了错误处理程序?如果是这样,您需要在此处记录错误。如果没有,请尝试发送MVCE,因为它无法正常工作的原因有很多。
猜你喜欢
  • 2015-12-20
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 2017-12-22
  • 2018-09-02
  • 2023-04-01
相关资源
最近更新 更多