如何解决FastCGI、Perl 和退出
在过去的几周里,我一直在磨练我用于项目的大型、几十年前的代码库的性能,并且有人建议我在这里查看类似 FastCGI 或 HTTP::Engine 的东西。我发现使用 FastCGI 非常简单,但有一个烦人的问题我发现答案不一。
我读过的一些文档说你永远不应该在通过 FastCGI 运行的脚本上调用 exit
,因为这会损害保持它持久加载的整个概念。别人说没关系。我的代码在很多地方都使用了 exit ,在这些地方确保没有任何东西继续执行是很重要的。例如,我有调用授权检查的受限访问组件:
use MyCode::Authorization;
our $authorization = MyCode::Authorization->new();
sub administration {
$authorization->checkCredentials();
#...Do restricted access stuff.
}
为了尽可能避免代码中出现错误,允许某人在不应该访问这些函数的情况下访问这些函数,checkCredentials
在生成用户后使用 exit() 结束进程友好的登录页面响应 if 答案是用户没有适当的凭据。例如:
sub checkCredentials {
#Logic to check credentials
if ($validCredential) {
return 1;
}
else {
# Build web response.
# Then:
exit;
}
}
}
我已经使用了它,这样我就不会意外地忽略继续进行的会导致安全漏洞的事情。目前,调用例程可以安全地假设它只从 checkCredentials
if 提供了正确的凭据取回控制权。
但是,我想知道是否需要删除这些调用以充分利用 FastCGI。 FCGI 的 $req->Finish()
(或 PSGI 中 HTTP::Engine 的等效项)是否足以替代?
解决方法
我读过说你不应该在通过 FastCGI 运行的脚本上调用 exit,
您不希望进程退出,因为使用 FastCGI 的目的是使用单个进程来处理多个请求(以避免加载时间等)。
所以你想要做的是覆盖 exit 以便结束你的特定于请求的代码,而不是 FastCGI 请求循环。
您可以覆盖 exit
,但必须在编译时进行。因此,请使用标志来表示覆盖是否处于活动状态。
our $override_exit = 0;
BEGIN {
*CORE::GLOBAL::exit = sub(;$) {
die "EXIT_OVERRIDE\n" if $override_exit;
CORE::exit($_[0] // 0);
};
}
while (get_request()) {
# Other setup...
eval {
local $override_exit = 1;
handle_request();
};
my $exit_was_called = $@ eq "EXIT_OVERRIDE\n";
log_error($@) if $@ && !$exit_was_called;
log_error("Exit called\n") if $exit_was_called;
# Other cleanup...
}
但这会产生一个可能无意中捕获的异常。所以让我们改用 last
。
our $override_exit = 0;
BEGIN {
*CORE::GLOBAL::exit = sub(;$) {
no warnings qw( exiting );
last EXIT_OVERRIDE if $override_exit;
CORE::exit($_[0] // 0);
};
}
while (get_request()) {
# Other setup...
my $exit_was_called = 1;
EXIT_OVERRIDE: {
local $override_exit = 1;
eval { handle_request() };
log_error($@) if $@;
$exit_was_called = 0;
}
log_error("Exit called\n") if $exit_was_called;
# Other cleanup...
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。