首页 > 解决方案 > 如何编写在 HTTP 响应发送到客户端后运行的 Plack 中间件?

问题描述

我的 Plack Web 服务通过与 fluentD 的 TCP 连接进行日志记录,我想在将响应发送回客户端后执行我的日志记录代码。这将减少响应时间(假设这是一个高请求量服务,值得进行这种性能优化)。

至少有一个其他的 web 框架,用于 nodejs,通过允许中间件向请求对象添加一个端事件处理程序来支持这一点。我查看了Plack::RequestPlack::Response接口,但没有看到类似的事件挂钩。

我想我可能会在我的中间件中对finalize方法进行本地覆盖,以强制框架在响应完成后进行日志记录,但如果可能的话,我想避免修改 Plack 内部。

是否有更好的方法可以将某些代码的执行推迟到向客户端发送响应之后?

标签: perlasynchronousmiddlewaredeferred-executionplack

解决方案


感谢LeoNerd和 ilmari 在MagNET 中的调试帮助#io-async

#!/usr/bin/env -S plackup -s Net::Async::HTTP::Server
use Future::AsyncAwait;
use Time::HiRes qw(time);
use Future::IO qw();
use Future::IO::Impl::IOAsync qw();

async sub mylogger {
    # simulate expensive run-time
    await Future::IO->sleep(1);
    open my $log, '>>', '/tmp/so-58605156.log';
    $log->say(time);
}

my $app = sub {
    my ($env) = @_;
    mylogger->retain;
    return [200, ['Content-Type' => 'text/plain'], [time]];
};

推荐阅读