Express.js 响应超时

Posted

技术标签:

【中文标题】Express.js 响应超时【英文标题】:Express.js Response Timeout 【发布时间】: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。 【参考方案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 在不增加套接字超时的情况下,这个答案似乎毫无用处。 ***.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 这就是我正在寻找的,用于调试目的。 讽刺的是,这正是我想要的。

以上是关于Express.js 响应超时的主要内容,如果未能解决你的问题,请参考以下文章

Express.js 对 Angular CORS 错误的响应

Node.js - Express.js JWT 总是在浏览器响应中返回一个无效的令牌错误

在前端使用 fetch 从 express.js 服务器获取响应

Express.JS:如何按名称而不是数字设置响应状态?

无法从使用 Express.js 和 SQL Server 创建的 api 获得任何响应

无法使用邮递员从 express.js 服务器获得响应