On May 19, 2004, at 9:48 AM, David Wheeler wrote:
Ah, thanks for the pointer. I'll be writing up an FAQ for the Mason project soon, and I'll include all of this info.
So here is the FAQ I'm proposing to submit to the Mason project. Geoff et al., I'd appreciate it if you gave it a quick read for accuracy, etc. Thanks!
=question
I'm using HTML::Mason::ApacheHandler and I have C<decline_dirs> disabled and
am using a dhandler to handle directory requests. But when a request comes
in without the final slash after the directory name, relative links are
broken. What gives?
=answer
Normally, Apache directory requests are handled by C<mod_dir>. One of the
primary functions of this core Apache module is to check the requested URI,
and if it is for a directory and there is no slash after the directory name,
C<mod_dir> appends the slash and redirects the browser to the new URL. This
ensures that relative URLs always work correctly.
However, C<mod_perl>, when it is compiled into Apache, sets itself up to get
the first stab at handling the response phase of requests. This is normally
what you want, but the upshot is that, unless C<mod_perl> declines the
request, neither C<mod_dir> nor any other response phase module ever gets a
chance to run. So Mason handles the request, but unfortunately it does not
decline requests for a directory when the final slash is missing. This will
be fixed in Mason 1.3, but not before then, as doing so breaks compatibility
with the existing behavior.
But there are a few approaches to changing this behavior without too much
trouble:
=over 4
=item *
You can add these lines to the top of your dhandler to handle the redirect
yourself:
<%init>;
use Apache::Constants qw(DIR_MAGIC_TYPE);
$m->abort(-1) if $r->content_type eq DIR_MAGIC_TYPE && $r->uri !~ m{/$};
</%init>
Here Mason declines the request, and therefore so does C<mod_perl>. This allows C<mod_dir> to handle the request, and C<mod_dir> will trigger the appropriate redirection.
=item *
You can use David Wheeler's Apache::Dir module from CPAN to replicate the
directory redirection behavior of C<mod_dir> in C<mod_perl>. Using it is
simple; just add it as a fixup handler wherever you're using
HTML::Mason::ApacheHandler to handle directory requests:
<Location /foo> PerlSetVar MasonDeclineDirs 0 PerlModule Apache::Dir PerlModule HTML::Mason::ApacheHandler SetHandler perl-script PerlFixupHandler Apache::Dir PerlHandler HTML::Mason::ApacheHandler </Location>
=item *
Recompile Apache to allow C<mod_dir> to handle requests before C<mod_perl>
does. This is simple to do thanks to Apache's C<--permute-module> configure
option. You can either give it the names of two modules to swap, e.g.:
--permute-module=dir:perl
or you can use special names "BEGIN" and "END" to move a module to the
beginning or end of the list, which might be what you want for C<mod_dir>,
e.g.:
--permute-module=dir:END
In this case, you might also need to change the value of the
C<DirectoryIndex> directive to F<dhandler> to prevent Apache from internally
redirecting to an existing F<index.html> file.
=item *
If you're running Apache 1.3, you can use the C<ClearModuleList> and
C<AddModule> directives to reorder the response phase handlers at server
startup time. The C<AddModule> directive can load either static or dynamic
modules; C<ClearModuleList> removes all loaded modules, so you'll need to
load them all again in the appropriate order; see the output of C<httpd -l>
for the complete list of loaded modules. The highest priority module loads
last, so you could do something like this:
ClearModuleList AddModule mod_so.c AddModule mod_perl.c AddModule mod_dir.c
Here again, you might also need to change the value of the C<DirectoryIndex>
directive to F<dhandler> to prevent Apache from internally redirecting to an
existing F<index.html> file.
=back
=begin comment
The status of this problem in mod_perl 2 is unknown at this time. It's
possible that it doesn't exist in mod_perl 2, because unlike in mod_perl 1,
mod_perl 2 is not configured to handle C<DIR_MAGIC_TYPE> requests, so
C<mod_dir> will handle them. But since Mason likes to handle directory
requests when C<decline_dirs> is disabled, it seems likely that Mason will
need to install a fixup handler to set itself up to handle such
requests. When HTML::Mason::ApacheHandler loads, it will need to call C<<
$s->add_config >> to add a PerlFixupHandler, which would likely look
something like this:
sub fixup_handler { my $r = shift; $r->handler('perl_script') # or $r->handler('modperl') unless $r->content_type eq DIR_MAGIC_TYPE && $r->uri =~ m{/$}; return DECLINED; }
So none of the above solutions should be necessary in mod_perl 2, but as of
this writing, I don't know how things work with Mason in mod_perl 2.
=end comment
=cut
Regards,
David
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]