2

在过去的几周里,我一直在磨练我在项目中使用的大型、几十年前的代码库的性能,这里有人建议我应该看看 FastCGI 或 HTTP::Engine 之类的东西。我发现使用 FastCGI 非常简单,但是有一个令人烦恼的问题,我发现答案不一。

我读过的一些文档说你永远不应该调用exit通过 FastCGI 运行的脚本,因为这会损害保持它持久加载的整个概念。其他人说没关系。我的代码在很多地方都使用了 exit,确保没有任何东西继续执行很重要。例如,我有调用授权检查的受限访问组件:

use MyCode::Authorization;
our $authorization = MyCode::Authorization->new();

sub administration {
    $authorization->checkCredentials();

    #...Do restricted access stuff.
}

为了尽可能避免代码中出现错误,允许某人在不应该访问这些功能的情况下访问这些功能,在使用checkCredentials登录页面生成用户友好的响应后,使用 exit() 结束进程,如果答案是用户没有适当的凭据。例如:

sub checkCredentials {
   #Logic to check credentials

   if ($validCredential) {
       return 1;
   }
   else {
       # Build web response.
       # Then:
       exit;
   }
}

}

我已经使用了它,这样我就不会意外地忽略导致安全漏洞的继续发生的事情。目前,调用例程可以安全地假设它只有在提供正确的凭据时才能获得控制checkCredentials

但是,我想知道是否需要删除这些调用以充分利用 FastCGI。FCGI $req->Finish()(或用于 HTTP::Engine 的 PSGI 中的等价物)是否足以替代?

4

1 回答 1

2

我读过说你永远不应该在通过 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...
}
于 2021-04-12T00:13:06.333 回答