Xerri
Xerri

Reputation: 5046

Express.js Response Timeout

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.

Upvotes: 111

Views: 228766

Answers (9)

Fe3back
Fe3back

Reputation: 1034

I hope it's not too late, this is a solution that I got from @Elliot404, and it's what I was looking for. I hope it helps.

export const timeOutMiddleWare = (
  req: Request,
  res: Response,
  next: NextFunction,
) => {
  setTimeout(() => {
    if (!res.headersSent) {
      res.status(408).send(`${req.method} ${req.originalUrl} Timed Out`);
      req.socket.end();
      res.json = () => {};
      res.send = () => {};
      res.sendStatus = () => {};
    }
  }, 1000 * 60 * 5);
  next();
};

Upvotes: 0

TiiGRUS
TiiGRUS

Reputation: 91

If you need to test your api, this solotion can you help. I used this in middleware to test my frontend. For exmaple: if you need to test loader in frontend.

const router = require('express').Router();
const { data } = require('./data');

router.get('/api/data', (req, res, next) => {
  setTimeout(() => {
      res.set('Content-Type', 'application/json')
      res.status(200).send(data)

      next()
  }, 2000)
})

module.exports = router;

Upvotes: 1

cyperpunk
cyperpunk

Reputation: 702

You can try:

return await new Promise((resolve) =>
  setTimeout(() => {
    resolve(resp);
  }, 3000),
);

In above code, 3000 = 3 sec. Change it according to your requirement.

I have not tried for very long scenarios though. Let me know the results in comments.

Upvotes: -4

bereket gebredingle
bereket gebredingle

Reputation: 13016

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();
});

Upvotes: 88

cider
cider

Reputation: 407

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
});

Upvotes: 5

rahul shukla
rahul shukla

Reputation: 253

request.setTimeout(< time in milliseconds >) does the job

https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback

Upvotes: 0

V31
V31

Reputation: 7666

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'));

Upvotes: 37

destino
destino

Reputation: 57

Before you set your routes, add the code:

app.all('*', function(req, res, next) {
    setTimeout(function() {
        next();
    }, 120000); // 120 seconds
});

Upvotes: -21

srquinn
srquinn

Reputation: 10501

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.

Upvotes: 90

Related Questions