在mod_perl 2下关闭响应

14

我正在尝试找出在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 子程序中返回一些内容。这导致我需要跟踪整个调用链,其中所有调用都必须返回一些内容,直到回到主要的 handler 。
unless (check_something()) { ...

我需要做像这样的事情:

my $check = check_something();
return $check if $check;

我还必须在主处理程序中做类似的事情,这对于某些情况处理来说非常丑陋。

有没有一种方法可以在嵌套调用中关闭请求,就像我尝试用示例说明的那样?

编辑:我发现我可以调用 goto LABEL 并将该标签放置在主handler子例程中的最后一个return之前。 它起作用,但仍然感觉像一个肮脏的黑客。 我真的希望有更好的方法。


2
我不是mod_perl2的专家,但通常这看起来像是你会使用异常处理的东西。在do_post_response()内部,使用die "We have a situation...";,并在handler()中使用eval块或更好地使用类似于Try::Tiny的模块进行捕获。如果需要区分自定义异常和其他可能由未捕获的故障引起的异常,请添加一些Exception::Class - mbethke
1个回答

2

我认为你仍然可以调用 exit(),因为 mod_perl 覆盖了 exit 函数的默认操作:

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


在提问之前,我尝试过使用“退出(exit)”语句。但是它没有起到作用,不能让处理程序返回它需要返回的内容,这和调用“die”函数一样。 - Francisco Zarabozo
你的代码或者mod_perl已经被修改,有另外一个问题。正如我链接文档中所解释的那样,mod_perl覆盖了exit。 - Daniel Wisehart
是的,它覆盖了exit,因为你在持久化解释器中,并且不希望它真正退出。如果使用真正的exit,那么实际上会杀死Apache线程。但是,它覆盖exit的事实只终止当前函数调用,但它没有返回任何东西给Apache,这就是问题所在,Apache需要一个实际的响应,否则它将把它视为请求失败。 - Francisco Zarabozo
你可以使用修改过的ModPerl::Util::exit版本来覆盖CORE::GLOBAL::exit,以便返回一个值给Apache,但是你需要捕获Apache调用mod_perl的每个地方,并且可能需要设置返回的退出。 - Daniel Wisehart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接