【问题标题】:How to suppress the default mod_perl error page in legacy CGI script using ModPerl::Registry如何使用 ModPerl::Registry 抑制旧 CGI 脚本中的默认 mod_perl 错误页面
【发布时间】:2012-01-07 11:22:55
【问题描述】:

我在 Perl 中有一个 CGI 脚本,它自己生成 HTTP 错误页面。我通过 ModPerl::Registry 在 mod_perl 下运行它,使用以下 Apache2 配置:

Alias /perl "/var/www/perl"
<Directory "/var/www/perl">
    SetHandler perl-script
    PerlResponseHandler ModPerl::Registry
    PerlOptions +ParseHeaders
    Options Indexes FollowSymlinks +ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

一切都很好,除了一个小问题:当标头中打印的 HTTP 状态不同于 200(例如 404)时,Apache 会在我自己生成的响应中附加一个默认的 HTML 错误文档。

以下面的简单 CGI 脚本为例:

#!/usr/bin/perl

use strict;
use warnings;

use CGI qw(:standard :escapeHTML -nosticky);
use CGI::Carp qw(fatalsToBrowser);

use Apache2::Const qw(:http :common);

our $cgi = CGI->new();

print $cgi->header(-type=>'text/html', -charset => 'utf-8',
                   -status=> '404 Not Found');
our $mod_perl_version = $ENV{'MOD_PERL'} ? " $ENV{'MOD_PERL'}" : '';
print <<"EOF";
<html>
<head>
<title>die_error_minimal$mod_perl_version 
</head>
<body>
404 error
</body>
</html>
EOF

exit;

使用上面提到的 Apache 配置运行它会导致

HTTP/1.1 404 Not Found
Date: Sun, 27 Nov 2011 13:17:59 GMT
Server: Apache/2.0.54 (Fedora)
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

<html>
<head>
<title>die_error_minimal mod_perl/2.0.1 
</head>
<body>
404 error
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /perl/die_error_minimal.cgi was not found on this server.</p>
<hr>
<address>Apache/2.0.54 (Fedora) Server at localhost Port 80</address>
</body></html>

请注意,将上面示例 CGI 脚本中的 exit; 替换为 return Apache2::Const::OK;return Apache2::Const::DONE;,正如关于 SO 的“How do I suppress the default apache error document in mod_perl?”问题中所建议的那样没有帮助 - 结果保持不变。

我应该在我的 Apache 配置中修复什么,或者我应该在我的 CGI 脚本中添加什么来抑制 mod_perl / Apache 将错误页面附加到生成的响应中?

【问题讨论】:

    标签: perl cgi mod-perl mod-perl2 mod-perl-registry


    【解决方案1】:

    FAQ 对我有用,在您的 CGI 完成后,在发送标头后,告诉 apache 状态正常,所以它不会发送 ErrorDocument http://search.cpan.org/~gozer/mod_perl-1.31/faq/mod_perl_faq.pod#So_how_do_I_use_mod_perl_in_conjunction_with_ErrorDocument%3F

    #!/usr/bin/perl --
    use strict; use warnings;
    use CGI;
    
    Main( @ARGV );
    exit( 0 );
    
    sub Main { 
        my404();
    #~ my $r = CGI::Simple->new->_mod_perl_request;
        my $r = CGI->new->r;
        $r->status(200);
        return;
    }
    sub my404 {
        my $cgi = CGI->new;
        print $cgi->header(  -status => 404 );
        print "<html><title>print404 says tough noogies</title>
    <body><h1>tough noogies</h1></body></html>";
    }
    __END__
    
    GET http://localhost/perl/print404
    User-Agent: lwp-request/6.03 libwww-perl/6.03
    
    404 Not Found
    Connection: close
    Date: Sun, 27 Nov 2011 20:55:39 GMT
    Server: Apache/2.0.54 (Win32) mod_ssl/2.0.54 OpenSSL/0.9.7g PHP/4.3.11 mod_perl/2.0.1 Perl/v5.8.9
    Content-Type: text/html; charset=ISO-8859-1
    Client-Date: Sun, 27 Nov 2011 20:55:39 GMT
    Client-Peer: 127.0.0.1:80
    Client-Response-Num: 1
    Client-Transfer-Encoding: chunked
    Title: print404 says tough noogies
    
    <html><title>print404 says tough noogies</title>
    <body><h1>tough noogies</h1></body></html>
    

    【讨论】:

    • 顺便说一句。您使用什么 Apache 配置?如果它与我的不同,您可以将其添加到响应中吗? TIA。
    • 不幸的是,在某些情况下(阅读:对于其他人),这会导致发送 HTTP 状态为“200 OK”的页面,而不是正确的错误信息。
    【解决方案2】:

    我似乎面临同样的问题:我将标头状态设置为 400 以防出错并返回 JSON 数组来描述实际错误。

    当我这样做时:

    print $main::cgi->header(@ret), $html;
    

    带变量:

    @ret: {'-type' => 'application/json','-charset' => 'utf-8','-status' => '400 Bad Request'}
    $html: '{"errors":{"short_name":["Missing!"]}}'
    

    我会这样结束:

    Status Code: 200 OK
    Content-Type: application/json; charset=utf-8
    Response: {"errors":{"short_name":["Missing!"]}<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
      <html><head>
      <title>400 Bad Request</title>
      </head><body>
      <h1>Bad Request</h1>
      <p>Your browser sent a request that this server could not understand.<br />
      </p>
      <hr>
      <address>Apache/2.2.3 (CentOS) Server at localhost Port 80</address>
      </body></html>
    

    使用 faquer 描述的方法确实会抑制错误文档,但仍会返回状态 200 OK,就像 Jakub Narębski 指出的那样。


    但是!我找到了一种解决方法,其中 $r 是 Apache2::RequestRec,使用以下方法: http://perl.apache.org/docs/2.0/user/coding/coding.html#Forcing_HTTP_Response_Headers_Out (否则你会使用 $r->send_http_header(),我猜)

    print $main::cgi->header(@ret), $html;
    my $r = $main::cgi->r;
    $r->rflush; # force sending headers (with headers set by CGI)
    $r->status(200); # tell Apache that everything was ok, dont send error doc.
    

    HTTP 响应:

    Status Code: 400 Bad Request
    Content-Type: application/json; charset=utf-8
    Response: {"errors":{"short_name":["Missing!"]}}
    

    Apache 配置:

    PerlModule ModPerl::PerlRun
    PerlModule CGI
    PerlModule Apache::DBI
    PerlRequire /var/www/html/startup.pl
    PerlSendHeader On
    

    .htaccess:

    <Files *.cgi>
     SetHandler  perl-script
     PerlHandler ModPerl::PerlRun
     Options ExecCGI
    </Files>
    

    【讨论】:

    • 要是我能多次投票就好了!这让我和我的团队更上一层楼。
    【解决方案3】:

    我的代码版本,但工作更稳定:

    #!/usr/bin/perl
    
    use CGI qw/:standard/ ;
    
    my $Content_of_webpage = 'Oops. 404 error ...' ;
    my $status_code = 404 ;
    
    
      if( $ENV{MOD_PERL} ) { # mod_perl ON
    
        my $r = CGI->new->r ;
        $r->status($status_code) ;
        $r->content_type("text/html; charset=UTF-8") ;
        $r->rflush ; # send the headers out << it is the trick :)
        $r->status(200) ;      
    
      }
      else { # mod_perl OFF
    
       my $cgi = CGI->new ;
       print $cgi->header( 
    
         -type    => "text/html",
         -status  => $status_code,
         -charset => 'UTF-8'
    
       );    
    
      }
    
     print $Content_of_webpage ;
    

    【讨论】:

      猜你喜欢
      • 2014-10-30
      • 2010-12-13
      • 1970-01-01
      • 2019-11-08
      • 1970-01-01
      • 1970-01-01
      • 2012-07-15
      • 1970-01-01
      • 2013-03-18
      相关资源
      最近更新 更多