I am exploring ways to abort client requests that are taking too long, thereby consuming server resources. Having read some sources (see below), I tried a solution like the following (as suggested here):
const express = require('express');
const server = express();
server
.use((req, res, next) => {
req.setTimeout(5000, () => {
console.log('req timeout!');
res.status(400).send('Request timeout');
});
res.setTimeout(5000, () => {
console.log('res timeout!');
res.status(400).send('Request timeout');
});
next();
})
.use(...) // more stuff here, of course
.listen(3000);
However, it seems not to work: the callbacks are never called, and the request is not interrupted. Yet, according to recent posts, it should.
Apart from setting the timeout globally (i.e. server.setTimeout(...)
), which would not suit my use case,
I have seen many suggesting the connect-timeout middleware.
However, I read in its docs that
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.
It is not clear to me how to "find the events that are taking long time" and "a way to cancel them", so I was wondering if someone could share their suggestions. Is this even the right way to go, or is there a more modern, "standard" approach?
Specs:
- Node 12.22
- Ubuntu 18.04
- Linux 5.4.0-87-generic
Sources:
- Express.js Response Timeout
- Express.js connect timeout vs. server timeout
- Express issue 3330 on GitHub
- Express issue 4664 on GitHub
Edit: I have seen some answers and comments offering a way to setup a timeout on responses or "request handlers": in other words, the time taken by the middleware is measured, and aborted if it takes too long. However, I was seeking for a way to timeout requests, for example in the case of a client sending a large file over a slow connection. This happens probably even before the first handler in the express router, and that is why I suspect that there must be some kind of setting at the server level.