Express.js连接超时和服务器超时的区别

5
我正在使用Express和Connect Timeout Middleware来处理超时。
它运行得很好,但是默认的node http服务器超时时间设置为两分钟。
因此,如果我想将我的超时中间件设置为大于两分钟的值,我还必须稍微增加http服务器的超时时间(否则我的连接超时处理程序不会被调用)。
const app = express();
const http = new Http.Server(app);

http.setTimeout((4 * 60 * 1000) + 1); <-- Must set this

app.use(timeout('4m')); 

我该如何避免这种情况?我有什么遗漏吗?


不,那只是它的工作原理。如果节点在您的中间件超时请求之前关闭套接字,则处理程序将不会被调用,因为此时请求已关闭。 https://github.com/expressjs/timeout/issues/32 - Kevin B
1个回答

6
如果您想使用connect-timeout中间件,由于该中间件不会更改套接字超时时间(默认为2分钟),因此您无法避免它。
有两种可能的方法可以避免这种情况,一种是使用server.setTimeout()request.setTimeout
如果您只想将超时时间更改为几个路由,并将默认超时时间保留给其他路由,则建议使用:request.setTimeout
app.use('/some-routes', (req, res, next) => {
   req.setTimeout((4 * 60 * 1000) + 1);
   next();
}, timeout('4m'));

除了将req.setTimeout设置为大于connect-timeout值的值之外,还可以放弃connect-timeout中间件并使用另一种解决方法,但这也不是理想的。

您可以查看此旧的Node.js问题:https://github.com/nodejs/node-v0.x-archive/issues/3460

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

app.use('/some-routes', (req, res, next) => {
    req.setTimeout(4 * 60 * 1000); // No need to offset

    req.socket.removeAllListeners('timeout'); // This is the work around
    req.socket.once('timeout', () => {
        req.timedout = true;
        res.status(504).send('Timeout');
    });

    next();
});


app.use(haltOnTimedout);

// But if the timeout occurs in the middle of a route
// You will need to check if the headers were sent or if the request timedout

app.get('/some-routes', async(req, res, next) => {
  
  // some async processing...
  await asyncOperation();
  
  if (!res.headersSent) // or !req.timedout 
    res.send('done');
 
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接