【问题标题】:Express.js Response TimeoutExpress.js 响应超时
【发布时间】:2014-03-09 14:44:29
【问题描述】:

问题

我一直在寻找 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 分钟。

【问题讨论】:

  • 我只会将其用于开发目的——我想不出有一个用例可以让您使用空路由发送生产代码。
  • 当然,我的观点是,它可能会出现请求会一直等待的问题。错误发生。我只是想设置一个响应超时以防万一。
  • 知道了——见下面的答案
  • 空路由作为网络蜘蛛的陷阱?
  • 当我尝试使用 Express.js(实际上是 json-server)构建测试服务以模拟/诱导各种错误情况时,这个“功能”实际上非常有用在服务器端。大多数此类错误对应于 HTTP 状态代码(例如 Bad Request),是的,但我也想在调用方端引起 SocketTimeoutException。

标签: node.js express timeout response settimeout


【解决方案1】:

已经有一个用于超时支持的连接中间件:

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 保留用于以下情况:

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

【讨论】:

  • 完美。甚至更简单。也感谢有关错误消息的提示。
  • 根据官方文档,不建议将其用作顶级中间件,至少不能这样。 github.com/expressjs/timeout
  • 在不增加套接字超时的情况下,这个答案似乎毫无用处。 stackoverflow.com/questions/12651466/…
  • @JeffFischer:调用socket.setTimeout() 只会增加调用超时事件之前的时间,但默认情况下不会切断连接nodejs.org/api/net.html#net_socket_settimeout_timeout_callback。在节点 v0.9.12 中,将 setTimeout API 添加到 http.server 对象中,以处理节点标准 http 库中此中间件的功能。但是,在 API 更新之前,此中间件将处理销毁套接字。你可以在这里阅读更多关于中间件的内容github.com/expressjs/timeout/blob/master/index.js
  • @SuperUberDuper:请将您的查询作为单独的问题发布,以便社区可以帮助您解决具体问题。
【解决方案2】:

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

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

灵感来自https://github.com/expressjs/express/issues/3330

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

【讨论】:

  • 这是一篇很老的帖子,但我没有使用任何额外的模块。查看问题中的“修复”部分
  • req.setTimeout 不是res.setTimeout
  • 我的实验表明,req.setTimeout() 回调根本没有被调用,server.setTimeout() 没有关闭连接,也没有停止处理请求。所以提供的解决方案并不完整。
  • 我的测试有 req.setTimeoutres.setTimeout 都可以工作。
【解决方案3】:

如果使用 Express 4.2 的更新,则超时中间件已被删除,因此需要手动添加

npm install connect-timeout

并且必须在代码中(根据评论编辑,如何将其包含在代码中)

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

【讨论】:

  • 没有DV,但有些人可能需要使用 var timeout = require('connect-timeout') 并且不得不在谷歌搜索它=)
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

    request.setTimeout(< time in milliseconds >) 完成这项工作

    https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback

    【讨论】:

      【解决方案6】:

      你可以试试:

      return await new Promise((resolve) =>
        setTimeout(() => {
          resolve(resp);
        }, 3000),
      );
      

      在上面的代码中,3000 = 3 秒。 根据您的要求更改它。

      不过,我还没有尝试过很长时间的场景。让我知道 cmets 中的结果。

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

        • 这不是等待120秒才回复客户吗?
        • @JeffreyvanNorden 这就是我正在寻找的,用于调试目的。
        • 讽刺的是,这正是我想要的。
        猜你喜欢
        • 2012-11-13
        • 1970-01-01
        • 2012-06-25
        • 2011-11-05
        • 1970-01-01
        • 2015-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多