如何在链的末尾添加快速中间件,无论什么(OK / FAIL响应)都被调用?

问题描述 投票:0回答:2

是否有办法将中间件添加到快速approuter链的末尾,该链被调用以跟踪是否发送了res /响应?

我的意思是,无论是否:

  • 发送响应(字符串,JSON等)
  • 静态服务文件。
  • 静态文件夹中找不到文件。
  • 达成了一个无所不能的回调。
  • 达到了错误的中间件。

例如,如果我想记录所有内容......

响应是否成功,即:它通过express.static( ... )中间件提供文件,从数据库提取的一些数据,或自定义中间件,或者再次......如果它失败/抛出错误......,是否有在最后调用回调的方法?

到目前为止,我可以理解,似乎,按照设计,如果静态文件成功提供(通过express.static),它不会调用next(),所以链停在那里。

对于使用res.send()的任何定制中间件,您通常不希望之后调用next(),因为它可能会导致一些不良副作用(标题重新发送错误)。

对于错误处理程序,这更容易,因为可以在此处捕获所有不成功的响应。

但它如何输出成功/不成功的回复?这可能是没有中间件的事情吗?

node.js express middleware
2个回答
1
投票

对于这样做,node.js和Express的异步架构存在概念上的困难。我将描述一般问题,然后讨论一些可能的解决方法。

首先,每个Express处理程序都可以是异步的。因此,它被调用并立即返回,并且该世界之外的任何人都不知道在最终发送响应之前它是否还在等待某些异步操作完成,或者它是否只是没有做任何事情。从字面上看,你无法从外界了解到。

其次,您可以监视给定的请求,以查看它是调用错误处理程序还是发送响应。由于上述原因,无法监视请求处理程序以查看它是否发送了任何内容 - 您无法知道它是否仍在等待某些异步操作完成。

所以,这是我能推荐的最好的:

  1. res.end()看它何时被召唤。这表明现在已完成响应(无论是错误还是成功)。您可以在mezt链接到上述评论的express-afterware模块中看到这样做的示例。一般的想法是你在链中很早就有自己的中间件覆盖res.end()所以你可以看到它被调用的时间。早期的中间件只会安装覆盖并调用next()来继续处理程序链。然后,当响应完成时,你的覆盖将看到res.end()被调用。这适用于发送响应的所有情况。
  2. 然后,您仍然需要处理没有响应的情况(这可能是由于错误的代码,因为所有请求最终都会得到响应)。我知道这样做的唯一方法是为请求实现某种超时。您可以使用内置机制server.setTimeout(),也可以在中间件中实现自己的(与步骤1中描述的相同的中间件)。然后,在您指定的某个超时之后,如果尚未发送任何响应,您将接管并发送一些错误响应。
  3. 在链的早期安装您自己的错误中间件,它将查看并记录所有错误。请注意,仍然会调用res.end(),因此即使出现错误,仍会触发步骤1中的行为(错误响应仍然会调用res.end())。

0
投票

我使用的解决方案最终与@idbehold的this one略有不同,但简而言之,在Express app中间件链的最顶层,我不得不挂钩回调res Response对象的finish事件,该事件被大多数触发(全部?)HTTP状态代码我需要跟踪成功提供的请求。

app.use( ( req, res, next ) => {
    res.on( 'finish', () => {
        var codeStr = String( res.statusCode );
        codeStr = codeStr[res.statusCode < 400 ? 'green' : 'red'];
        var output = [req.method.green, req.fullUrl().green, codeStr];
        trace( output.join( ' ' ) );
    } );

    next();
});

我现在可以得到这样的东西:

enter image description here

编辑

好的!因此,如果您的中间件链的“末端”还有一个错误处理程序,该错误处理程序提供错误的404代码,它将触发finish对象上的res事件。

这种错误处理程序的示例:

app.use( ( err, req, res, next ) => {
    trace( "Error!".red );
    trace( err );

    res.status( 404 ).send(); // Triggers 'finish' on res.
})
© www.soinside.com 2019 - 2024. All rights reserved.