I revisited the issue of 404 handling in CGI and Apache::Registry today and here's what I found. For illustration, here's a minimal CGI script which can illustrate the issue:
#!/usr/bin/perl print "Status: 404\r\nContent-Type: text/html\r\n\r\nHello"; You can review the status codes being returned by accessing the script with LWP: lwp-request -sS http://server.com/t.cgi | less What I would like to have happen is for ErrorDocument to be triggered and deliver the standard 404 page. When the script runs in CGI, it does cause Apache to return a proper 404 status code, but is apparently too late to trigger ErrorDocument, so just "Hello" is printed instead. When the script runs under Apache::Registry, the 404 status code is also set correctly, but Apache prints my "Hello" output *and* sends the ErrorDocument content. This interplay is mentioned some mod_perl documentation, with the suggestion to suppress the ErrorDocument content by returning a "200" code later on: 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? The good news that it at least that I think there's a way to have 404 handling code that works in both CGI and Apache::Registry. The method would be to send our own full HTML page and then suppress the ErrorDocument output under mod_perl, perhaps using a method like those docs suggest. It's tempting to considering patching CGI.pm or another toolkit module to address this: CGI.pm could automatically call $r->status(200); after $r->send_cgi_headers to suppress ErrorDocument sending. OTOH, there are probably a number of people that now expect the current behavior, even if it can result and in the unexpected and undesirable result of having ErrorDocument content appended to your own content. Another alternative would be write my own "404" routine that always sets 404, but returns nothing in mod_perl (so the ErrorDocument is displayed) but returns the full error document under CGI. I would love for this be solved at a toolkit level so folks don't have to keep re-inventing solutions for this. Have I missed a better way to handle this? Mark