Hi all. Can anybody explain historical reasons of ModPerl::RegistryCooker default_handler() implementation? We can see the following piece of code there:
# handlers shouldn't set $r->status but return it, so we reset the # status after running it my $old_status = $self->{REQ}->status; my $rc = $self->run; my $new_status = $self->{REQ}->status($old_status); return ($rc == Apache2::Const::OK && $old_status != $new_status) ? $new_status : $rc; The goal of ModPerl modules is "Run unaltered CGI scripts under mod_perl". If scripts are unaltered, how they can change $r->status? I think, answer should be - 'in no way'. Why we need to reset status then? I see no reasons. But this solution makes us impossible to set status from 'altered' scripts correctly. Did anyone can explain, why this code appears and for which scenarios it come? Apache's mod_cgi.c module returns OK regardless of the r->status, which was set from script output. Why ModPerl handler should behave differently? One good example about problems, what are introduced by this solution, is 404 status. Let`s look into small script: #!/usr/bin/perl -w use strict; use CGI; my $q = CGI->new; #### Variant 1 print $q->header(-charset => "windows-1251", -type => "text/html", -status=>'404 Not Found'); print "SMALL RESPONSE"; #### Variant 2 print $q->header(-charset => "windows-1251", -type => "text/html", -status=>'404 Not Found'); #print 'BIG RESPONSE:' . '*' x 8192; Under CGI it prints only "SMALL/BIG RESPONSE" string with 404 status code into browser. Under mod_perl, browser get status 200 instead of 404 and script response is appended by default Apache error-handler content (like 'Status: OK \n /path/to/script.pl was not found on this server'). If we print 'big response', then browser get status 404 and apache error-handler appended content changes to 'Not Found \n The requested URL /perl/test.pl was not found on this server.'. The reasons for such behaviour is what scripts are using CGI.pm which handles MOD_PERL. So, they are practically 'altered' and can set $r-status inside of them. After script executes, we have r->status = 404. But ModPerl::RegistryCooker set r->status to 200 and return 404 as handler status - so apache ErrorDocument directive begin to work (under mod_cgi handler status is OK, so no error processing occurs). Also, due to r->status changed, we get 200 into browser. Most interesting, what we get 404 status logged into access log anyway. Ok, the next example - completely unaltered script: #!/usr/bin/perl -w use strict; print "Status: 404 Not Found\n"; print "Content-Type: text/html; charset=windows-1251\n\n"; #Small response print 'NOTFOUND:' . '*' x 81; #Big response #print 'NOTFOUND:' . '*' x 8192; When response is small, then 8k buffer is not filled, and r->status does not changed internally before cgi headers parsed on buffer flush. So, we get r->status == 200, and handler status is 200 too. After headers are parsed, r->status become 404, but mod_perl handler returns status 200 to apache -- Regards,, Pavel mailto:pavel2...@ngs.ru --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@perl.apache.org For additional commands, e-mail: dev-h...@perl.apache.org