在 mod_perl 2 下关闭响应
Posted
技术标签:
【中文标题】在 mod_perl 2 下关闭响应【英文标题】:Close response under mod_perl 2 【发布时间】:2017-01-06 00:44:38 【问题描述】:我正在尝试找出是否有办法在 mod_perl 2 下完成响应而不返回主处理程序。到目前为止,还没有在文档中找到一种方法。以下是我想要实现的示例:
#!/usr/bin/perl
# This is some mod_perl handler
use strict;
use warnings;
use Apache2::Const ':common';
sub handler
my $r = shift;
if ($r->method eq 'POST')
# just to do something as example
do_post_response($r);
$r->content_type('text/plain');
print "Thank you, goodbye.";
return Apache2::Const::OK;
sub do_post_response
my $r = shift;
unless (check_somthing())
# Suppose I find a situation that requires
# a different response than normal...
$r->content_type('text/plain');
print "We have a situation...";
$r->something_to_finish_the_request_immediatly(Apache2::Const::OK);
在常规的 Perl 脚本中,作为独立运行或在 mod_cgi 下运行,我可以只使用新响应 exit()
,但在 mod_perl
下,我需要在原始 handler
subroutine 中返回一些内容。这导致我跟踪整个调用链,所有调用链都必须返回一些东西,直到我回到主要的handler
。
例如,而不是:
unless (check_something()) ...
我需要做以下事情:
my $check = check_something();
return $check if $check;
而且我还必须在主处理程序中做类似的事情,这对于某些情况处理来说是相当难看的。
有没有办法在嵌套调用中关闭请求,就像我试图用我的示例说明的那样?
编辑:我发现我可以调用 goto LABEL
并将该标签放置在主 handler
subroutine 中的最后一个返回之前。它有效,但仍然感觉像一个肮脏的黑客。我真的希望有更好的方法。
【问题讨论】:
我不是 mod_perl2 方面的专家,但通常这看起来像是你会使用例外的东西。在 do_post_response() 中,使用die "We have a situation...";
并在 handler() 中使用 eval
块或更好地使用像 Try::Tiny
这样的模块来捕获它。添加一些Exception::Class
如果您需要将您的自定义异常与其他未捕获的故障可能导致的异常区分开来。
【参考方案1】:
我认为你仍然可以调用 exit(),因为 mod_perl 会覆盖 exit 所做的:
退出
在正常的 Perl 代码中,exit() 用于停止程序流并退出 Perl 解释器。但是在 mod_perl 下,我们只希望停止程序流而不杀死 Perl 解释器。
如果您的代码包含 exit() 调用并且可以继续使用它们,则您不应采取任何措施。 mod_perl 担心用自己的版本覆盖 exit() 函数,这会停止程序流,并执行所有必要的清理,但不会杀死服务器。这是通过覆盖来完成的:
*CORE::GLOBAL::exit = \&ModPerl::Util::exit;
https://perl.apache.org/docs/2.0/user/coding/coding.html
【讨论】:
我在问这个问题之前尝试了退出。它不起作用,它不会让处理程序返回它需要返回的东西,它和调用一个骰子一样。 那么你的代码有另一个问题或者你的mod_perl被修改了。 mod_perl 覆盖退出,如我链接的文档中所述。 是的,它会覆盖退出,因为您处于持久解释器中并且您不希望它真正退出。如果您使用真正的退出,那么您实际上会杀死 Apache 线程。然而,它覆盖 exit 的事实只是终止了当前的函数调用,但它没有向 Apache 返回任何内容,这就是问题所在,Apache 需要一个实际的响应,否则它会将其视为请求中的失败。 您可以使用 ModPerl::Util::exit 的修改版本覆盖 CORE::GLOBAL::exit,该版本向 Apache 返回一个值,但您必须捕获 Apache 调用的每个位置mod_perl 并且可能会有一个出口来设置返回。以上是关于在 mod_perl 2 下关闭响应的主要内容,如果未能解决你的问题,请参考以下文章