Express.js响应超时


71

问题

我一直在寻找Express.js的请求/响应超时,但是一切似乎都与连接有关,而不是请求/响应本身。

如果请求花费很长时间,则应该超时。显然,这不应该发生,但即使是一个简单的错误,如具有不调用回调或不调用的路由处理程序res.send(),浏览器将永远等待答复。

空路由处理程序就是一个很好的例子。

app.get('/sessions/', function(req, res, callback){});

固定

之前 添加了以下内容app.use(app,router);并且似乎添加了超时功能。有人对此有任何经验/意见吗?

app.use(function(req, res, next){
    res.setTimeout(120000, function(){
        console.log('Request has timed out.');
            res.send(408);
        });

    next();
});

请注意,我已将超时设置为2分钟。


1
我只会将其用于开发目的–我想不出一个用例来发送带有空路径的生产代码。
srquinn 2014年

如果可以的话,我的意思是,可能会有一个问题,就是请求将一直等待。发生错误。我只是想设置一个响应超时,以防万一。
Xerri 2014年

Gotcha –请参阅下面的答案
srquinn 2014年

5
空路作为网络蜘蛛的陷阱?
原型

当我尝试使用Express.js(实际上是json-server)来构建测试服务,以在服务器端模拟/引发各种错误情况时,此“功能”实际上变得非常有用。多数此类错误对应于HTTP状态代码(例如Bad Request),是的,但我也想在调用者端引起SocketTimeoutException。
FerencDósa-Rácz18年

Answers:


79

已经有用于超时的Connect中间件支持:

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

如果您打算将Timeout中间件用作上述的顶级中间件,则该haltOnTimedOut中间件必须是堆栈中定义的最后一个中间件,并用于捕获超时事件。感谢@Aichholzer的更新。

边注:

请记住,如果滚动自己的超时中间件,则4xx状态代码用于客户端错误,而5xx状态代码用于服务器错误。408保留给以下情况:

在服务器准备等待的时间内,客户端未发出请求。客户端可以在以后的任何时间重复请求而无需修改。


完善。更简单。也感谢您提供有关错误消息的提示。
Xerri 2014年

2
根据官方文档,不建议将其用作顶级中间件,至少不是那样。github.com/expressjs/timeout
Stefan

在不增加套接字超时的情况下,这个答案似乎毫无用处。 stackoverflow.com/questions/12651466/…–
杰夫·菲舍尔

@JeffFischer:调用socket.setTimeout()只会增加调用超时事件之前的时间,但默认情况下nodejs.org/api/net.html#net_socket_settimeout_timeout_callback不会断开连接。在节点v0.9.12中,向该http.server对象添加了setTimeout API,以处理节点标准http lib中该中间件的功能。但是,在该API更新之前,该中间件将处理销毁套接字的情况。您可以在这里阅读有关中间件内部的更多信息github.com/expressjs/timeout/blob/master/index.js
srquinn 2015年

1
@SuperUberDuper:请将您的查询作为一个单独的问题发布,以便社区可以帮助您解决特定问题。
srquinn

30

如果正在使用Express 4.2进行更新,则超时中间件已被删除,因此需要使用

npm install connect-timeout

并且必须在代码中进行编辑(根据注释以及如何将其包括在代码中)

 var timeout = require('connect-timeout');
 app.use(timeout('100s'));

1
不是DV,但是有些人可能需要使用var timeout = require('connect-timeout')并不得不在Google上搜索它=)
Mohamed Salad

29

您不需要其他npm模块来执行此操作

var server = app.listen();
server.setTimeout(500000);

https://github.com/expressjs/express/issues/3330的启发

要么

app.use(function(req, res, next){
    res.setTimeout(500000, function(){
        // call back function is called when request timed out.
    });
    next();
});

这是一篇很老的文章,但是我没有使用任何额外的模块。看看问题中的“修复”部分
Xerri

2

如果您想使用超时中间件并排除特定路由:

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


-22

在设置路线之前,请添加以下代码:

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

27
这不是在等待120秒钟之后才回复客户吗?
杰弗里·范·诺登

3
@JeffreyvanNorden这就是我正在寻找的用于调试目的的东西。
5ervant
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.