2011-11-27 40 views
3

在傳統CGI腳本中抑制默認mod_perl錯誤頁面我有一個Perl中的CGI腳本,它自己生成HTTP錯誤頁面。我經由ModPerl::Registry mod_perl下運行它,使用以下的Apache2配置:如何使用ModPerl :: Registry

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),阿帕奇附加一個默認的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; 

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> 

注意與上述結果提到Apache配置運行它的是,在例如CGI腳本上面替換exit;return Apache2::Const::OK;return Apache2::Const::DONE;,如「How do I suppress the default apache error document in mod_perl?」中所建議的那樣,對SO沒有幫助 - 結果保持不變。

我應該在我的Apache配置中修復什麼,或者我應該添加到我的CGI腳本以抑制mod_perl/Apache生成響應的附加錯誤頁面?

回答

5

的常見問題對我的作品,你的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> 
+0

BTW。你使用什麼** Apache配置?如果它與我的不同,可以將它添加到響應中嗎? TIA。 –

+0

謝謝,它的作品。 –

+2

不幸的是,在某些情況下(閱讀:對於其他人),這會導致發送HTTP狀態爲「200 OK」的頁面而不是正確的錯誤信息。 –

3

我似乎對着同樣的問題:如果發生錯誤,我將標題狀態設置爲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,就像JakubNarę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> 
+0

如果只有我可以不止一次地對此讚賞!這讓我和我的團隊成爲了沃爾。 – StrikeForceZero

2

我的代碼版本,但工作更穩定:

#!/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 ; 
相關問題