Giter Site home page Giter Site logo

timeout's Introduction

connect-timeout

NPM Version NPM Downloads Build Status Test Coverage Gratipay

Times out a request in the Connect/Express application framework.

Install

This is a Node.js module available through the npm registry. Installation is done using the npm install command:

$ npm install connect-timeout

API

NOTE This module is not recommend as a "top-level" middleware (i.e. app.use(timeout('5s'))) unless you take precautions to halt your own middleware processing. See as top-level middleware for how to use as a top-level middleware.

While the library will emit a 'timeout' event when requests exceed the given timeout, node will continue processing the slow request until it terminates. Slow requests will continue to use CPU and memory, even if you are returning a HTTP response in the timeout callback. For better control over CPU/memory, you may need to find the events that are taking a long time (3rd party HTTP requests, disk I/O, database calls) and find a way to cancel them, and/or close the attached sockets.

timeout(time, [options])

Returns middleware that times out in time milliseconds. time can also be a string accepted by the ms module. On timeout, req will emit "timeout".

Options

The timeout function takes an optional options object that may contain any of the following keys:

respond

Controls if this module will "respond" in the form of forwarding an error. If true, the timeout error is passed to next() so that you may customize the response behavior. This error has a .timeout property as well as .status == 503. This defaults to true.

req.clearTimeout()

Clears the timeout on the request. The timeout is completely removed and will not fire for this request in the future.

req.timedout

true if timeout fired; false otherwise.

Examples

as top-level middleware

Because of the way middleware processing works, once this module passes the request to the next middleware (which it has to do in order for you to do work), it can no longer stop the flow, so you must take care to check if the request has timedout before you continue to act on the request.

var bodyParser = require('body-parser')
var cookieParser = require('cookie-parser')
var express = require('express')
var timeout = require('connect-timeout')

// example of using this top-level; note the use of haltOnTimedout
// after every middleware; it will stop the request flow on a timeout
var app = express()
app.use(timeout('5s'))
app.use(bodyParser())
app.use(haltOnTimedout)
app.use(cookieParser())
app.use(haltOnTimedout)

// Add your routes here, etc.

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

app.listen(3000)

express 3.x

var express = require('express')
var bodyParser = require('body-parser')
var timeout = require('connect-timeout')

var app = express()
app.post('/save', timeout('5s'), bodyParser.json(), haltOnTimedout, function (req, res, next) {
  savePost(req.body, function (err, id) {
    if (err) return next(err)
    if (req.timedout) return
    res.send('saved as id ' + id)
  })
})

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

function savePost (post, cb) {
  setTimeout(function () {
    cb(null, ((Math.random() * 40000) >>> 0))
  }, (Math.random() * 7000) >>> 0)
}

app.listen(3000)

connect

var bodyParser = require('body-parser')
var connect = require('connect')
var timeout = require('connect-timeout')

var app = connect()
app.use('/save', timeout('5s'), bodyParser.json(), haltOnTimedout, function (req, res, next) {
  savePost(req.body, function (err, id) {
    if (err) return next(err)
    if (req.timedout) return
    res.send('saved as id ' + id)
  })
})

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

function savePost (post, cb) {
  setTimeout(function () {
    cb(null, ((Math.random() * 40000) >>> 0))
  }, (Math.random() * 7000) >>> 0)
}

app.listen(3000)

License

MIT

timeout's People

Contributors

dead-horse avatar dougwilson avatar dsummersl avatar fishrock123 avatar jiimaho avatar jonathanong avatar juliangruber avatar kevinburke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

timeout's Issues

Make timeout action more flexible

Actually it's impossible to change the response generated when timeout occurs.
This limitation does not allow the package to be integrated with Apollo Server for example.

It could be cool to has an option to change the default behaviour:

cb(createError(503, 'Response timeout', {
      code: 'ETIMEDOUT',
      timeout: delay
    }))

Make this configurable via middleware.json

We're using loopback and it's hard to use this. The reason is, that this requires a contructor parameter, which does not work when adding it via middleware.json. I would appreciate if the extension could work from the 'params' as well.

Yarn certificate has expired.

getting this when trying to install with yarn:

error An unexpected error occurred: "https://registry.yarnpkg.com/connect-timeout: certificate has expired". info If you think this is a bug, please open a bug report with the information provided in "/home/bruno/Documents/Projetos/oton_contabil/api/yarn-error.log". info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

Should remove listener to timeout event

At this moment with default settings there is a subscription added

req.on('timeout', onTimeout(delay, next))

It would be a good idea to unsubscribe from it to avoid mem leak in a long run.

Could be something like:

const onTimeoutCb = delay => {
  req.removeListener('timeout', onTimeoutCb);
  onTimeout(delay, next)();
};
req.on('timeout', onTimeout);

Upgrade Dependencies

Hello, I'm facing a bug related to the version of a dependency.
If possible update the the package "http-errors" to a newer version 1.6.1 => 2.0.0

TypeError: Cannot read properties of undefined (reading 'split')
    at toIdentifier (node_modules/http-errors/index.js:257:14)
    at forEachCode (node_modules/http-errors/index.js:228:16)
    at Array.forEach (<anonymous>)
    at populateConstructorExports node_modules/http-errors/index.js:226:9)
    at Object.<anonymous> (node_modules/http-errors/index.js:29:1)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Module._compile (node_modules/source-map-support/source-map-support.js:521:25)
    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at require.extensions..jsx.require.extensions..js (/tmp/ts-node-dev-hook-21923819908444608.js:114:20)
    at Object.nodeDevHook [as .js] (node_modules/ts-node-dev/lib/hook.js:63:13)
[ERROR] 09:08:27 TypeError: Cannot read properties of undefined (reading 'split')

Race condition: Can't set headers after they are sent

I'm debugging a "Can't set headers after they are sent" error in my app and one theory is that it's coming from this middleware.

I'm curios about the intended behavior for this scenario:

  • Route middleware working, starts doing I/O
  • Timeout occurs in this middleware, error is sent to the response
  • Route I/O finishes and route calls res.send()
  • Crash with "Can't set headers after they are sent" error

Is there some mechanism for canceling the in process route middleware or for preventing it from trying to set headers again?

Calling `next` after a timeout crashes Express 4.x server

The following Express 4.x server crashes :

var express = require('express');
var timeout = require('connect-timeout');

var app = express()
    .use(timeout(1000))
    .use(function (req, res, next) {
        // simulate database action that takes 2s
        setTimeout(function () {
            next(); // ERROR here 
        }, 2000)
    })
    .use(haltOnTimedout)
    .listen(3000);


function haltOnTimedout(req, res, next) {
    console.log('----------called---------');
    if (!req.timedout) next();
}

It seems that calling next after the timeout has occurred (and response terminated) is itself an error and haltOnTimedout isn't called:

http.js:691
    throw new Error('Can\'t set headers after they are sent.');
          ^
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
    at node_modules\express\lib\application.js:156:9
    at node_modules\express\lib\router\index.js:140:5
    at node_modules\express\lib\router\index.js:265:10
    at next (node_modules\express\lib\router\index.js:165:14)
    at null._onTimeout (\propErrorHandled.js:9:13)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

It works fine with Express 3.x / Connect 2.x / Connect 3.x (tested by @dougwilson). Perhaps once the reason is tracked this issue should be ported to Express bug list.

How to catch "Can't set headers after they are sent."

Because of some implementation issue in my code i got the bug:

Possibly unhandled Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:690:11)
    at ServerResponse.header (/home/bijosh/Work/server_projects/my-sample-project/node_modules/express/lib/response.js:718:10)

there were a condition in code that I'm invoking response.status().json() multiple times which was causing the issue.
I am using Winston logger module for logging.

On debugging I've gone through 2 cases -

Test 1 (invoking res.json() 2 times in consecutive line):

res.status().json();
res.status().json();

Test 2 (invoking res.json() 2 times, but 2nd call is happening inside timeout callback with 0 timeout):

res.status().json();
setTimeout(function () {
  res.status().json();
}, 0);

In both cases, i got the above error, but in 1st case logger is not catching error, but in 2nd case logger is catching it.

Anyone have idea. Why!!

Also I wanted to know how to catch this error somewhere in express app.

Thank You.

Documentation Update

For easier understanding, kindly add to documentation that this middleware does not override the server's default timeout.

In case of the setting timeouts greater than the default of 120000 ms, the usage shall be as below

var express = require('express')
var timeout = require('connect-timeout')

var app = express();

let SERVER_TIMEOUT = 300000;
app.use(timeout((SERVER_TIMEOUT/1000)+"s"))

//Routers here
let server = app.listen(3000);
server.timeout = SERVER_TIMEOUT;

(or)

other better examples.

It could just save a lot of time for the beginners.

Inconsistent test case documentation.

The test case 'should respond with 408 Request timeout' suggests that a 408 should be returned on timeout, while the library returns a 503. Personally I'm not quite clear as to the difference between 408/503 - I expect the correct response code depends on the context of the timeout.

clearer documentation

I am looking for something that will actually halt processing requests which take beyond a certain amount of time - e.g. the CPU will stop executing any commands for that request. As far as I can tell the library simply fires the given callback when requests take longer than the given amount but does not do anything to cancel or halt execution of that request.

Assuming the latter is close to impossible in node, but it would be great if the README for this library would be clearer on this point.

Can't set headers after they are sent.

Pardon me if this has been asked a million time but It's not clear how to best handle timeouts. The following script will crash the server since res.send is called after the timeout. I could wrap res.send in an if !res.headersSent but it seems a little excessive to do that for every route. I'm not sure how to best handle this situation.

var express = require('express');
var timeout = require('connect-timeout');

var handleTimeout = function (req, res, next) {
    if (!req.timedout) next();
};

var app = express()
    .use(timeout(500))
    .use(handleTimeout)
    .get("/", function (req, res, next) {
        setTimeout(function () {
            // This causes "Error: Can't set headers after they are sent."
            res.send({peaches:"yummy", turnips:"yucky"}); 
        }, 1000);
    })
    .use(handleTimeout)
    .listen(8888, function(){
            console.log('Server started on port 8888');
        });

Error:

Starting child process with 'node timeout.js'
Server started on port 8888
ServiceUnavailableError: Response timeout
    at IncomingMessage.<anonymous> (/Users/jw/Desktop/timeout/node_modules/connect-timeout/index.js:69:8)
    at IncomingMessage.emit (events.js:95:17)
    at null._onTimeout (/Users/jw/Desktop/timeout/node_modules/connect-timeout/index.js:41:11)
    at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)

http.js:689
    throw new Error('Can\'t set headers after they are sent.');
          ^
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:689:11)
    at ServerResponse.header (/Users/jw/Desktop/timeout/node_modules/express/lib/response.js:718:10)
    at ServerResponse.send (/Users/jw/Desktop/timeout/node_modules/express/lib/response.js:163:12)
    at ServerResponse.json (/Users/jw/Desktop/timeout/node_modules/express/lib/response.js:249:15)
    at ServerResponse.send (/Users/jw/Desktop/timeout/node_modules/express/lib/response.js:151:21)
    at null._onTimeout (timeout/timeout.js:13:17)
    at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
Program node timeout.js exited with code 8

Rename module

All these modules should have nice generic names and not imply that they only work on connect or express :)

publish

wtf do i call this. can't think of a name that isn't already taken npm. god damn global namespaces

erroneous documentation

I believe require('timeout') should be require('connect-timeout'). The latter worked for me and the former appears to be some other unrelated module in NPM.

What is the associate between this library and http's timeout

I noticed that the node.js's native http also have a timeout. And I do understand that timeout is about socket connection during it's inactive . And now, this library is about a http request . So I'm wondering what will happen if the value of expreejs/timeout is large then http's timeout ?

Override timeout for a route

Hi,

I have app level timeout set with the following code:
app.use(connectTimeout('30s'));

I want to override the 30s timeout in a particular route and increase it's value. I tried passing it in middleware but it doesn't work.

router.post("/process", connectTimeout('1000s'), async (req, res) => {

This route still times out in 30 seconds. Please tell me how to do this?

How to change timeout response?

The timeout is working, but I can't log and response the users that way. I need to send a response in my way.

Hou can I do this using the module?

Turning off response timeouts

I have a long running job and i want to turn off the response timeout.

The only thing somehwat relevant i found is this:

req.clearTimeout()
Clears the timeout on the request. The timeout is completely removed and will not fire for this request in the future.

Here it mentions requests. Can i remove the timeout on the response of the server?

Extending the timeout

So far as I understand it, the timeout value is set when you add the connect-timeout middleware when initializing the express server, so the same timeout applies to every request the comes in thereafter (that matches the route concerned).

What I'm finding is that for some incoming GET requests, there is a particular combination of options in the request that causes a network fetch to a remote resource than is not very reliable. For those requests, I'd like to relax the timeout value for connect-timeout somewhat, to allow for a few fetch retries.

But I can't see any way to change the timeout value 'on the fly', for a particular request. The only control I can see over the timeout is to use req.clearTimeout() whilst processing a request. This is helpful, but timeout is completely removed and will not fire for this request in the future. This is not entirely what I'm looking to achieve... I would like to retain a timeout, but just a slightly longer one.

Is what I'm asking for really naughty, breaking established rules of good practice of which I'm not aware? Or is it a reasonable thing to want to do?

Need single release node 0.8 compatible

Apparently connect 2.x and therefore express 3.x are using this module, which has never been compatible with node.js 0.8. Since the only compatibility issue is the res.headersSent bit, I think we should make a single last release that works with node.js 0.8 just like the express-session module.

@jonathanong thoughts?

"Can't set headers after they are sent" error crashes the app

Hi,

When I use this middleware in my app I have encountered the following problem. (I elaborated in a test script):

const timeout = require('connect-timeout');
const express = require('express');
const app = express();

app.use(timeout(1 * 1000));

app.get('/test', (req, res) => {
    setTimeout(function() {
        res.send('triggered');
    }, 2 * 1000);
});

app.listen(9988);

Then I got the error message and crashed the app:
curl -XGET http://localhost:9988/test

ServiceUnavailableError: Response timeout
    at IncomingMessage.<anonymous> (/Users/yjq/testground/nodejs-test/node_modules/connect-timeout/index.js:84:8)
    at emitOne (events.js:96:13)
    at IncomingMessage.emit (events.js:188:7)
    at Timeout._onTimeout (/Users/yjq/testground/nodejs-test/node_modules/connect-timeout/index.js:49:11)
    at ontimeout (timers.js:386:14)
    at tryOnTimeout (timers.js:250:5)
    at Timer.listOnTimeout (timers.js:214:5)
_http_outgoing.js:357
    throw new Error('Can\'t set headers after they are sent.');
    ^

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:357:11)
    at ServerResponse.header (/Users/yjq/testground/nodejs-test/node_modules/express/lib/response.js:730:10)
    at ServerResponse.send (/Users/yjq/testground/nodejs-test/node_modules/express/lib/response.js:170:12)
    at Timeout._onTimeout (/Users/yjq/testground/nodejs-test/index.js:9:13)
    at ontimeout (timers.js:386:14)
    at tryOnTimeout (timers.js:250:5)
    at Timer.listOnTimeout (timers.js:214:5)

And then the app crashed

ServiceUnavailableError: Response timeout

Hello

I defined the timeout as middleware as follows.

That way everything works fine but when you want to see the timeout message and define it as

App.use (timeout ('0s')); // To see the timeout error message

App.use (haltOnTimedout);

Function haltOnTimedout (req, res, next) {

    If (! Req.timeout) {
        //console.dir("Its here);
        Next ();
    } Else {
        Res.status (408) .json ({
            'Message': 'Timeout',
            'Status': '408',
            'Content': 'Timeout'
        });
    }
}

I get the following error

ServiceUnavailableError: Response timeout
    At IncomingMessage (C: \ Users \ Jake \ Desktop \ Projects \ RestApi \ Server \ Node js \ Solutions \ node-rest \ node_modules \ connect-timeout \ index.js: 84: 8)
    At emitOne (events.js: 96: 13)
    At IncomingMessage.emit (events.js: 188: 7)
    At timeout._onTimeout (C: \ Users \ Jake \ Desktop \ Projects \ RestApi \ Server \ Node js \ Solutions \ node-rest \ node_modules \ connect-timeout \ index.js: 49:11)
    At ontimeout (timers.js: 365: 14)
    At tryOnTimeout (timers.js: 237: 5)
    At Timer.listOnTimeout (timers.js: 207: 5)
_http_outgoing.js: 356
    Throw new Error ('Can ' t set headers after they are sent. ');

I'm doing something wrong, how can I check when a timeout happens?

req.timedout always come out to be false irrespective of timeout happens or not

I am using connect-timeout to handle timeout for route.While this works correct but for the condition req.timedout this always come out out to be false irrespective of timeout or not. req.timedout always come out to be false irrespective of timeout happens or not.

[var express = require('express')
var bodyParser = require('body-parser')
var timeout = require('connect-timeout')

var app = express()
app.post('/save', timeout('1s'), bodyParser.json(), haltOnTimedout, function (req, res, next) {
  savePost(req.body, function (err, id) {
    if (err) return next(err)
    if (req.timedout) return
    res.send('saved as id ' + id)
  })
})

function haltOnTimedout (req, res, next) {
  console.log(req.timedout, "==req.timedout");
  if (!req.timedout) next()
}

function savePost (post, cb) {
  setTimeout(function () {
    cb(null, ((Math.random() * 40000) >>> 0))
  }, (Math.random() * 7000) >>> 0)
}
]

Screenshot 2020-07-16 at 12 23 06 PM

Screenshot 2020-07-16 at 12 23 23 PM

Clarification on req.clearTimeout()

Hi,

I was just looking for some clarification on the req.clearTimeout() function -- does it reset the timeout (ie. start the timeout counter from 0) or does it stop connect-timeout from monitoring the request for a timeout? I wasn't sure based on the info in the README.

Thanks in advance!

Mike

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.