ndequeker
ndequeker

Reputation: 8000

Node Express specific timeout value per route

I'm developing a Node v4.2.4 application using Express v4.13.4. Now I would like to increase the timeout time for a specific upload route.

From what I've read and experienced:

However, I'm lost when trying to implement the connect-timeout middleware for the upload route.

Application setup

const app = express();
app.use(cors());
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: false }));
app.use(passport.initialize());

app.use('/uploads', uploadRoutes);
app.use(errorHandler);

function errorHandler(err, req, res, next) {
  if (err.code && err.code === 'ETIMEDOUT') {
    if (!res.headersSent) {
      res
        .status(408)
        .send({
          success: true,
          message: 'Timeout error'
        });
    }
  }

  next(err);
}

const server = app.listen(config.port);

Upload route definition

router.route('/:uploadId/upload-files')
  .post(timeout('3m'),
    require('./actions/upload-files').prepareHandler,
    require('./actions/upload-files').uploadHandler(),
    require('./actions/upload-files').responseHandler);

However, when uploading the files I do see the error from express-timeout after 3 minutes ONLY in the command line's console. The request is still in progress and no status code of 408 is returned.

After 4 minutes I finally see the 408 status and 'Timeout error' as part of the response object.

For requests to other routes I get the net::ERR_EMPTY_RESPONSE error after 4 minutes.

If I log the value for server.timeout, the value is 120000 (2 minutes).

My questions

Upvotes: 16

Views: 23015

Answers (2)

GavinBelson
GavinBelson

Reputation: 2794

Easy way to increase timeout on a route:

app.post('/some_route', (req, res) => {
   req.setTimeout(60 * 1000); //use req. this sets timeout to 60 seconds
});

OR

If you wanted to increase the timeout on the server for all routes, you can edit your app.js:

var serverApp = app.listen();
serverApp.setTimeout(60 * 1000); //use sets timeout to 60 seconds

Obviously, use the server setting sparingly. You don't want to tie up your server with long requests, so most of the time using the route specific timeouts is better architecture..

Upvotes: 8

ndequeker
ndequeker

Reputation: 8000

I've solved it using the following route configuration:

'use strict';

const ms = require('ms');
const express = require('express');
const router = express.Router();

router.route('/upload-files')
  .post(
    setConnectionTimeout('12h'),
    require('./actions/upload-files').responseHandler
  );

function setConnectionTimeout(time) {
  var delay = typeof time === 'string'
    ? ms(time)
    : Number(time || 5000);

  return function (req, res, next) {
    res.connection.setTimeout(delay);
    next();
  }
}

exports.router = router;

Where the key logic is the following middleware:

  function (req, res, next) {
    res.connection.setTimeout(delay);
    next();
  }

I hope this reference will come in handy for others.

Upvotes: 19

Related Questions