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:[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]