Express.js Response Timeout

159,700

Solution 1

There is already a Connect Middleware for Timeout support:

var timeout = express.timeout // express v3 and below
var timeout = require('connect-timeout'); //express v4

app.use(timeout(120000));
app.use(haltOnTimedout);

function haltOnTimedout(req, res, next){
  if (!req.timedout) next();
}

If you plan on using the Timeout middleware as a top-level middleware like above, the haltOnTimedOut middleware needs to be the last middleware defined in the stack and is used for catching the timeout event. Thanks @Aichholzer for the update.

Side Note:

Keep in mind that if you roll your own timeout middleware, 4xx status codes are for client errors and 5xx are for server errors. 408s are reserved for when:

The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time.

Solution 2

You don't need other npm modules to do this

var server = app.listen();
server.setTimeout(500000);

inspired by https://github.com/expressjs/express/issues/3330

or

app.use(function(req, res, next){
    req.setTimeout(500000, function(){
        // call back function is called when request timed out.
    });
    next();
});

Solution 3

An update if one is using Express 4.2 then the timeout middleware has been removed so need to manually add it with

npm install connect-timeout

and in the code it has to be (Edited as per comment, how to include it in the code)

 var timeout = require('connect-timeout');
 app.use(timeout('100s'));

Solution 4

In case you would like to use timeout middleware and exclude a specific route:

var timeout = require('connect-timeout');
app.use(timeout('5s')); //set 5s timeout for all requests

app.use('/my_route', function(req, res, next) {
    req.clearTimeout(); // clear request timeout
    req.setTimeout(20000); //set a 20s timeout for this request
    next();
}).get('/my_route', function(req, res) {
    //do something that takes a long time
});
Share:
159,700

Related videos on Youtube

Xerri
Author by

Xerri

Updated on July 08, 2022

Comments

  • Xerri
    Xerri almost 2 years

    PROBLEM

    I've been looking for request/response timeouts for Express.js but everything seems to be related to the connection rather than the request/response itself.

    If a request is taking a long time, it should be timed out. Obviously this shouldn't happen but even a simple mistake as having a route handler without a call to the callback or without res.send(), the browser will keep waiting for a reply forever.

    An empty route handler is a perfect example of this.

    app.get('/sessions/', function(req, res, callback){});
    

    FIX

    I added the following before app.use(app,router); and it seemed to add the timeout functionality. Does anyone have any experience/opinion on this?

    app.use(function(req, res, next){
        res.setTimeout(120000, function(){
            console.log('Request has timed out.');
                res.send(408);
            });
    
        next();
    });
    

    Note that I've set the timeout to 2 minutes.

    • srquinn
      srquinn over 10 years
      I would use this for development purposes only – I can't think of a single use case where you would want to ship production code with empty routes.
    • Xerri
      Xerri over 10 years
      If course, my point with that is that its possible to have an issue where the request would just keep waiting. Bugs happen. I'm just trying to set a response timeout just in case.
    • srquinn
      srquinn over 10 years
      Gotcha – see answer below
    • prototype
      prototype over 8 years
      empty routes as a trap for web spiders?
    • Ferenc Dósa-Rácz
      Ferenc Dósa-Rácz about 6 years
      This 'feature' actually came quite useful when I was trying to use Express.js (well, actually json-server) to build a test service with the purpose of simulating / inducing all manners of error conditions on the server side. Most such errors corresponded to HTTP status codes (e.g. Bad Request), yes, but I also wanted to cause a SocketTimeoutException on the caller end.
    • 欧阳维杰
      欧阳维杰 about 6 years
      what will happen if the value of response timeout is large then the http's timeout?
  • Xerri
    Xerri over 10 years
    Perfect. Even simpler. Thanks for the tip on the error message as well.
  • Stefan
    Stefan over 9 years
    According to the official documentation, using it as top-level middleware is not recommended, at least not just like that. github.com/expressjs/timeout
  • Jeff Fischer
    Jeff Fischer over 9 years
    This answer seems to be fairly useless without increasing the socket timeout. stackoverflow.com/questions/12651466/…
  • srquinn
    srquinn over 9 years
    @JeffFischer: calling socket.setTimeout() only increases the time before the timeout event is called but the connection is not severed by default nodejs.org/api/net.html#net_socket_settimeout_timeout_callba‌​ck. In node v0.9.12, a setTimeout API was added to the http.server object to handle the functionality of this middleware in the node standard http lib. However, before that API update this middleware would handle destroying the socket. You can read more on the innards of the middleware here github.com/expressjs/timeout/blob/master/index.js
  • SuperUberDuper
    SuperUberDuper almost 8 years
    I have the following app.get('/timeout', function (req, res) { for (var i = 0; i < 1111211111; i++) {} res.send('d') }) but I always get d back, why?, Note, I'm using app.use(timeout('1s'));
  • srquinn
    srquinn almost 8 years
    @SuperUberDuper: Please post you query as a separate question so the community can help you with your specific issue.
  • SuperUberDuper
    SuperUberDuper almost 8 years
  • Jeffrey van Norden
    Jeffrey van Norden almost 7 years
    Isn't this just waiting for 120 second before ever replying to the client?
  • Mohamed Salad
    Mohamed Salad about 6 years
    Didn't DV, but some people probably need to use var timeout = require('connect-timeout') and had to search google for it =)
  • Xerri
    Xerri over 5 years
    This is a very old post but I didn’t use any extra modules. Check out the ‘fix’ part in the question
  • 5ervant - techintel.github.io
    5ervant - techintel.github.io about 5 years
    Error: Cannot find module 'connect-timeout'
  • 5ervant - techintel.github.io
    5ervant - techintel.github.io about 5 years
    @JeffreyvanNorden That's what I'm looking for, for debugging purpose.
  • Farasi78
    Farasi78 over 3 years
    @5ervant use $ npm install connect-timeout here is a link to documentation expressjs.com/en/resources/middleware/timeout.html
  • DollarAkshay
    DollarAkshay about 3 years
    req.setTimeout not res.setTimeout
  • Slava Fomin II
    Slava Fomin II almost 3 years
    My experiments show that req.setTimeout() callback is not getting called at all and the server.setTimeout() is not closing the connection and is not stopping the request from being processed. So the provided solution is not complete.
  • Michael Cox
    Michael Cox over 2 years
    My test have req.setTimeout and res.setTimeout both working.
  • AndrewLeonardi
    AndrewLeonardi over 2 years
    Ironically this is exactly what I was looking for.
  • Paul Fabbroni
    Paul Fabbroni about 2 years
    res.setTimeout worked for me not req