Re: Inconsistency with dhandlers
David Wheeler <[email protected]>
| Newsgroups | gmane.comp.web.mason.devel |
|---|---|
| Message-ID | <[email protected]> |
Okay, here is my contribution to the FAQ to address this issue. Let me
know if you need any more information.
Regards,
David
------------
=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 DECLINED);
$m->abort(DECLINED)
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
It's unlikely that this problem 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. 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. To do so,
HTML::Mason::ApacheHandler 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')
if $r->content_type ne DIR_MAGIC_TYPE || $r->uri =~ m{/$};
return HTTP_OK;
}
So none of the above solutions should be necessary in mod_perl 2, but
as of
this writing, I doubt that Mason handles directories with mod_perl 2 at
all.
=end comment
=cut
-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g.
Take an Oracle 10g class now, and we'll give you the exam FREE.
http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click