Categories
Express JavaScript Nodejs

Add Timeout Capability to Express Apps with connect-timeout

Spread the love

To prevent requests from taking too long, it’s a good idea to have a maximum processing time for requests.

We can do this by making requests that take too long to time out. The connect-timeout middleware can help us do this.

In this article, we’ll look at how to use it to implement time out features in our app.

One Catch

This middleware sends a timeout response back to the client if a request exceeds the maximum time that we specify.

However, in the background, it’ll continue to run whatever was running before the request timed out.

Resources like CPU and memory will continue to be used until the process terminates.

We may need to end the process and free up any resources that it was using.

Usage

The timeout function takes 2 arguments. The first is the time for the maximum time for the request to process, and the second is an options object.

Time

The time is either a number in milliseconds or a string accepted by the ms module.

On timeout, req will emit timeout .

Options

The options object takes an optional object that can have the following property:

  • respond — controls if this module will response in the form of forwarding an error. If it’s true , the timeout error is passed to the next so that we may customize the response behavior. The error has a timeout property and status code 503. The default is true .

req.clearTimeout()

The clearTimeout method clears the timeout on the request and it won’t fire for this request in the future.

req.timedout

A boolean that is true if timeout is fired and false otherwise.

Example

We can use it as follows as top-level middleware. We have to stop the flow to the next middleware if the request timed out so they won’t run.

For example, we can write:

const express = require('express');  
const bodyParser = require('body-parser');  
const timeout = require('connect-timeout');  
const app = express();  
const haltOnTimedout = (req, res, next) => {  
  if (!req.timedout) {  
    next();  
  }  
}  
app.use(timeout('5s'))  
app.use(bodyParser.json({ extended: true }))  
app.use(haltOnTimedout)
app.get('/', (req, res) => {  
  res.send('success');  
})
app.listen(3000);

Then our endpoints will time out after 5 seconds and only allow to proceed beyond the bodyParser middleware if the request hasn’t timed out.

We can check time out by adding setTimeout to our route handler as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const timeout = require('connect-timeout');  
const app = express();  
const haltOnTimedout = (req, res, next) => {  
  if (!req.timedout) {  
    next();  
  }  
}  
app.use(timeout('5s'))  
app.use(bodyParser.json({ extended: true }))  
app.use(haltOnTimedout)
app.get('/', (req, res) => {  
  setTimeout(() => {  
    res.send('success');  
  }, Math.random() * 7000);  
})
app.listen(3000);

The some requests will time out and get us a 503 response.

We can catch the error and handle it ourselves as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const timeout = require('connect-timeout');  
const app = express();  
const haltOnTimedout = (req, res, next) => {  
  if (!req.timedout) {  
    next();  
  }  
}
app.use(timeout('5s'))  
app.use(bodyParser.json({ extended: true }))  
app.use(haltOnTimedout)
app.get('/', (req, res, next) => {  
  setTimeout(() => {  
    if (req.timedout) {  
      next();  
    }  
    else {  
      res.send('success');  
    }  
  }, Math.random() * 7000);  
})
app.use((err, req, res, next) => {  
  res.send('timed out');  
})
app.listen(3000);

In the setTimeout callback, we check the req.timedout property and called next() if it times out so that it’ll go to our error handler.

Note that we have the error handler after our route so calling next will go to our error handler.

We should get timed out if our request timed out instead of the error message and stack trace.

Conclusion

We can use the connect-timeout middleware to implement time out functionality for our routes.

This sends a 503 response if a request times out, but it doesn’t clear all the resources that’s being used for the request and end the process that’s still running.

We can check if a request has timed out with the req.timedout property.

Finally, we can catch the error by adding our own error handler after our routes and calling next .

Leave a Reply

Your email address will not be published.

If you like the content of this blog, subscribe to my email list to get exclusive articles not available to anyone else.