aidong xia
aidong xia

Reputation: 25

Express.js connect-timeout. how to handle when timout fire,where it generate error

When I use the connect-timeout when timeout fire, it shows

[2015-07-31 11:46:18.983] [ERROR] console - ServiceUnavailableError:
Response timeout
      at IncomingMessage. (/opt/data/nlb-server-dev/node_modules/connect-timeout/index.js:69:8)
      at IncomingMessage.EventEmitter.emit (events.js:95:17)
      at null._onTimeout (/opt/data/nlb-server-dev/node_modules/connect-timeout/index.js:41:11)
    at Timer.listOnTimeout as ontimeoutenter
[2015-07-31 11:46:18.990] [ERROR] exception-log - Server web-server-1: Caught
exception: Error: Can't set headers after they are sent. stack: Error:
Can't set headers after they are sent.   at
ServerResponse.OutgoingMessage.setHeader (http.js:691:11)    at
ServerResponse.res.set.res.header
(/opt/data/nlbserverdev/node_modules/express/lib/response.js:561:10)  
at ServerResponse.res.send
(/opt/data/nlbserverdev/node_modules/express/lib/response.js:133:12)
at ServerResponse.res.json
(/opt/data/nlb-server-dev/node_modules/express/li
b/response.js:210:15)at ServerResponse.res.send
(/opt/data/nlb-server-dev/node_modules/express/lib/response.js:121:21)
at /opt/data/nlb-server-dev/app/services/web/adminHandler.js:110:9 at
Object.utils.invokeCallback
(/opt/data/nlb-server-dev/app/util/utils.js:9:8) at
/opt/data/nlb-server-dev/app/dao/baseDao.js:48:13 at Query._callback
(/opt/data/nlb-server-dev/app/dao/mysql/mysql.js:55:9) at
Query.Sequence.end
(/opt/data/nlb-server-dev/node_modules/mysql/lib/proto
col/sequences/Sequence.js:78:24)

I handle with it as follows, but it does not work

function errorFilter(err, req, res, next){
  logger.warn(err.stack);
  errcode = err.statusCode || 500;
  msg = err.message || 'server error!';
  res.send(errcode, msg);
}

I see the middiwire I can't find how do handle it. Please help me.

Upvotes: 1

Views: 5378

Answers (1)

trex005
trex005

Reputation: 5115

Whereas your error handler could use a little tweaking, that is not your problem.

As the error indicates, you are trying to send headers after they have already been sent. Since connect-timeout ends itself as soon as headers are emitted for res, you are either trying to send headers before connect-timeout is called, or after it's timer has ticked.

  1. If it is before connect-timeout is called, it is fairly simple, you just need to make sure that it's middleware is before any other middleware with output. This option seems rather unlikely, as usually any middleware with output is not going to pass the buck.
  2. If it is after the timer ticks, then your function, which only knows to stop processing if you tell it to, is trying to output something. To resolve this, check req.timedout at minimum before you send anything, and if it is true, stop processing

Exibit A

var express = require('express');
var app = express();
var timeout = require('connect-timeout');
var createError = require('http-errors'); //this is required by connect-timeout, so you should already have it

app.get('/long/query/',timeout('5s'),function(req,res,next){
    if(req.timedout)return next(createError(503,'Response timeout'));
    //Something that takes a long time
    if(req.timedout)return next(createError(503,'Response timeout'));
    req.send("I processed that for you!");
});

var errorFilter = function(err, req, res, next){
    logger.warn(err.stack); //the stack is actually not going to be helpful in a timeout
    if(!res.headersSent){ //just because of your current problem, no need to exacerbate it.
        errcode = err.status || 500; //err has status not statusCode
        msg = err.message || 'server error!';
        res.status(errcode).send(msg); //the future of send(status,msg) is hotly debated
};

app.use(errorFilter);
app.listen(80);

Upvotes: 2

Related Questions