You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by David Wheeler <da...@kineticode.com> on 2004/05/11 23:12:08 UTC

Apache::Dir

G'day.

I recently had a need to have mod_dir in Apache 1.3 work even when I 
was using a Perl handler. It turns out that mod_dir does its thing 
during the response phase. So I created a quick Perl module to do what 
I want. Here's the description:

     This simple module is designed to be a partial replacement for the
     standard Apache mod_dir module. One of the things that module does 
is
     to redirect browsers to a directory URL ending in a slash when they
     request the directory without the slash. Since mod_dir seems do its
     thing during the Apache response phase, if you use a Perl handler, 
it
     won't run. This can be problematic if the Perl handler doesn't 
likewise
     take the directory redirecting into account.

     A good example is HTML::Mason. If you've disabled Mason's 
decline_dirs
     parameter (MasonDeclineDirs 0 in httpd.conf), and there's a 
dhandler in
     the directory /foo, then for a request for /foo, /foo/dhandler will
     respond. This can wreak havoc if you use relative URLs in the 
dhandler.
     What really should happen is that a request for /foo will be 
redirected
     to /foo/ before Mason ever sees it.

     This is the problem that this module is designed to address. Thanks 
to
     mod_perl's ability to stack handlers, you can just make sure that
     Apache::Dir handles requests before Mason does. Configuration would
     then look something like this:

       <Location /foo>
         PerlSetVar  MasonDeclineDirs 0
         PerlModule  Apache::Dir
         PerlModule  HTML::Mason::ApacheHandler
         SetHandler  perl-script
         PerlHandler Apache::Dir HTML::Mason::ApacheHandler
       </Location>

You can download it to try it out here:

   http://theory.kineticode.com/code/Apache-Dir-0.01.tar.gz

There are at least two issues that I need to address before releasing 
it on CPAN, though:

1. Doug has the Apache::Dir namespace reserved. Did he have some 
working code for this already?

   http://search.cpan.org/~dougm/

2. Maybe this isn't necessary in Apache 2. I really don't know, so I'm 
asking you guys. Can mod_dir be stacked/chained to execute before a 
Perl handler in Apache 2/mod_perl 2?

Thanks!

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

David Wheeler wrote:
> Thanks for the great reply, Geoff. Sorry I didn't get back to you 
> sooner. I've ben snorkeling for the last week. :-)

no problem :)


> Right, I understand now. Too bad mod_dir doesn't run during the fixup 
> phase or something. Seems kinda dumb to run it during the response  phase.
> 
>> in apache 2.0 it's a bit different.  when a module registers a hook  with
>> apache - say mod_rewrite's hook into translation - the module itself 
>> tells
>> apache the order.  a module can choose to run first, last, or a few 
>> other
>> things.  this is good for developers but kinda hard on administrators
>> because there is absoltely no ability to do the kind of thing in 2.0.
> 
> 
> Um, I'm confused. I thought you just said you _could_ do it in 2.0.

no, you can't do it in 2.0.  at least not yet.  well, I mean you _can_ but
it requires altering mod_perl source code between the autogeneration (perl
Makefile.PL) and make.  or altering mod_dir.

> 
>> I was
>> trying to give mod_perl the ability to dynamically alter its own
>> order  and
>> it worked for linux but not win32.  one of several threads is here if 
>> you're
>> interested:
>>
>>    http://marc.theaimsgroup.com/?l=apache-modperl-
>> dev&m=107723862520564&w=2
> 
> 
> Doesn't seem like a major loss if you can still do it statically, so to 
> speak.

yeah.  at first I thought about a compile time option.  then stas thought we
could use macros to pick up on -D switches.  then I figured out how to have
it directive-oriented, which we all preferred.  then we tested the solution
on win32 and *boom*

> I'm not sure how to document this, though; it sounds like 
> mod_perl 2 folks will _have_ to use my Apache::Dir module (now 
> registered to me--thanks Doug!) if they want the mod_dir behavior, 
> while Apache 1 users can use the ClearModules/AddModule solution if 
> they'd rather. Or am I missing something?

I'll need to look into it more, but I think that's backwards.  mp1 registers
itself for DIR_MAGIC_TYPE, which means it will be invoked when mod_dir
ordinarily would.  mp2 does not handle DIR_MAGIC_TYPE so it will pass on
those requests and mod_dir will take over.

I guess this means that while for mp2 mod_dir will work just fine, folks
like Mason will _not_ be able to rely on their PerlResponseHandler being
invoked for directories.

> 
>> ok, the way the content generation phase is dispatched is completely
>> different in apache 2.0.  in 1.3 apache only dispatched to registered
>> handlers - if r->handler was perl-script then apache called mod_perl, 
>> for
>> instance.  in 2.0 apache calls _every_ handler, and every hander has  the
>> responsibility to check r->handler itself.
> 
> 
> Oh, so you can more easily chain handlers? That's cool.

no, not really.  the first OK still ends the chain, so it's not really about
stacking handlers at all.  really, I don't know the rationale behind it, and
it seems incredibly less efficient than the way things used to be in apache
1.3.  for chaining handlers you would want to use output filters, which are
uber cool.


>> really, the number of people that actually want to handle directories
>> themselves is few (if any), so setting $r->handler('perl-script') from  a
>> fixup handler isn't that big of a deal.
> 
> 
> Well, Mason works this way. If a request comes in for /foo/ and there's 
> a file F</foo/dhandler> and Mason is configured to handle directory 
> requests, then /foo/dhandler will execute. It will also execute if a 
> request comes in for /foo/bar and there is no "bar" directory. 
> Requiring that Mason install a fixup handler will probably be somewhat 
> of a PITA for Mason users accustomed to a simpler configuration 
> (although I guess it's really just one more line in their httpd.conf, 
> isn't it? Or, no! Mason can add a fixup handler itself when it loads, 
> eh?).

yeah, Mason will be able to use $s->add_config from module load to add a
PerlFixupHandler, which should essentially satisfy the requirements right
there.  or even as a PerlTypeHandler, especially now that mod_mime no longer
 has its strangle hold on that phase.

> No, I'm not using 2.0. I just want to make sure I can document for 
> people how to get the same behavior from the two versions.

I think that the way to get mp2 to behave like mp1 wrt directories is to use
the fixup phase to:

  $r->handler('perl-script')  #  or $r->handler('modperl')
    if $r->content_type == DIR_MAGIC_TYPE && $r->uri !~ m{/$};

as for Apache::Dir, I guess it becomes a mp1-only solution.  at least that's
what I think I see after this rather long digression :) you might want to
benchmark the difference between Apache::Dir as you have it and simply using
a fixup handler to clear the PerlHandler stack under the proper conditions
then letting mod_dir handle the directory after all.  of maybe I'm just more
confused now...

HTH

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 24, 2004, at 5:35 PM, Stas Bekman wrote:

> That's not quite click-able, isn't it? :)

Stupid Wiki + Mail client. It's the last question here:

   http://www.masonhq.com/?FAQ:ServerConfiguration

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Stas Bekman <st...@stason.org>.
David Wheeler wrote:
> On May 24, 2004, at 5:26 PM, Geoffrey Young wrote:
> 
>> yeah, that looks and sounds right.  cool.
> 
> 
> Whew! Added to the Mason FAQ:
> 
>    http://www.masonhq.com/?FAQ:ServerConfiguration#h- 
> i_m_using_html__mason___apachehandler_and_i_have___decline_dirs__disable 
> d_and_am_using_a_dhandler_to_handle_directory_requests__but_when_a_reque 
> st_comes_in_without_the_final_slash_after_the_directory_name__relative_l 
> inks_are_broken__what_gives_

That's not quite click-able, isn't it? :)

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 24, 2004, at 5:26 PM, Geoffrey Young wrote:

> yeah, that looks and sounds right.  cool.

Whew! Added to the Mason FAQ:

    
http://www.masonhq.com/?FAQ:ServerConfiguration#h- 
i_m_using_html__mason___apachehandler_and_i_have___decline_dirs__disable 
d_and_am_using_a_dhandler_to_handle_directory_requests__but_when_a_reque 
st_comes_in_without_the_final_slash_after_the_directory_name__relative_l 
inks_are_broken__what_gives_

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

David Wheeler wrote:
> On May 24, 2004, at 5:17 PM, Geoffrey Young wrote:
> 
>> ok, that still looks funky.  here's where I'm coming from, which may be
>> different than where you're coming from :)
> 
> 
> Heh, okay, sorry for my density. ;-)_

no problem.  I'm the dense one most of the time :)


>> I think what you want to do is activate mod_perl only for things where
>> mod_dir would ordinarily be invoked, namely when the URI resolves to a
>> directory and the URI does not end with a slash.
> 
> 
> That's exactly right. 

actually, I think I mucked up the explanation, but you get it right below :)

> So how 'bout this?
> 
>   sub fixup_handler {
>      my $r = shift;
>      $r->handler('perl_script') # or $r->handler('modperl')
>        if $r->content_type eq DIR_MAGIC_TYPE && $r->uri =~ m{/$};
>      return HTTP_OK;
>  }
> 
> So for directories without a final slash, mod_dir will handle the
> request; for directories with a final slash, we're telling Apache to let
> mod_perl (and therefore Mason) handle it. For everything else, we let be
> what will be (whatever SetHandler determines).

yeah, that looks and sounds right.  cool.

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 24, 2004, at 5:17 PM, Geoffrey Young wrote:

> ok, that still looks funky.  here's where I'm coming from, which may be
> different than where you're coming from :)

Heh, okay, sorry for my density. ;-)_

> mod_perl is typically set up to handle stuff correctly.  the problem 
> exists
> where mod_perl is handling directories without trailing slashes, which
> should typically be handled by mod_dir.
>
> the above logic activates mod_perl as the content handler for any URI 
> that
> isn't a unix directory.  that logic should be reserved for SetHandler 
> or
> similar directives within httpd.conf.

Ah, right.

> I think what you want to do is activate mod_perl only for things where
> mod_dir would ordinarily be invoked, namely when the URI resolves to a
> directory and the URI does not end with a slash.

That's exactly right. So how 'bout this?

   sub fixup_handler {
      my $r = shift;
      $r->handler('perl_script') # or $r->handler('modperl')
        if $r->content_type eq DIR_MAGIC_TYPE && $r->uri =~ m{/$};
      return HTTP_OK;
  }

So for directories without a final slash, mod_dir will handle the 
request; for directories with a final slash, we're telling Apache to 
let mod_perl (and therefore Mason) handle it. For everything else, we 
let be what will be (whatever SetHandler determines).

> not for the fixup phase.  OK will terminate the translation, auth, 
> authz,
> and mime phases early, though.  for the remaining phases OK just means 
> "move
> along", so it will have the same effect.  the general practice within 
> Apache
> is to use DECLINED to mean "I didn't do anything (or I don't want 
> Apache to
> think I did)" while OK means "I did something," even for phases where 
> OK and
> DECLINED will have the same effect (like fixups)

Gotcha, thanks.

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
>> I think that 'unless' should be 'if' - if the request is for a directory,
>> and if the directory has a trailing slash, set the content handler to be
>> perl-script.  I think the above logic demorgans out to
>>
>>   if ( ! $r->content_type eq DIR_MAGIC_TYPE || $uri !~ m{/$} )
>>
>> which isn't quite right.  sorry if that is what I wrote before.
> 
> 
> Don't think so, it's my fault for not thinking it through (I'm so used
> to telling mod_perl _not_ to handle something! I'll change it to 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 DECLINED;
>  }

ok, that still looks funky.  here's where I'm coming from, which may be
different than where you're coming from :)

mod_perl is typically set up to handle stuff correctly.  the problem exists
where mod_perl is handling directories without trailing slashes, which
should typically be handled by mod_dir.

the above logic activates mod_perl as the content handler for any URI that
isn't a unix directory.  that logic should be reserved for SetHandler or
similar directives within httpd.conf.

I think what you want to do is activate mod_perl only for things where
mod_dir would ordinarily be invoked, namely when the URI resolves to a
directory and the URI does not end with a slash.

but you're closer to this than I am, so ymmv.

>> returning OK from a fixup handler is probably more idiomatic.
> 
> 
> Oh, so that doesn't prevent any others from running? 

not for the fixup phase.  OK will terminate the translation, auth, authz,
and mime phases early, though.  for the remaining phases OK just means "move
along", so it will have the same effect.  the general practice within Apache
is to use DECLINED to mean "I didn't do anything (or I don't want Apache to
think I did)" while OK means "I did something," even for phases where OK and
DECLINED will have the same effect (like fixups)

> Okay, great, thanks a million!

sure thing :)

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 24, 2004, at 12:55 PM, Geoffrey Young wrote:

>>   <%init>;
>>   use Apache::Constants qw(DIR_MAGIC_TYPE);
>>   $m->abort(-1) if $r->content_type eq DIR_MAGIC_TYPE && $r->uri !~ 
>> m{/$};
>>   </%init>
>
> -1 is DECLINED, right?

For Mason it is, at any rate. If it's the same as DECLINED, I'll use 
that, instead.

>>  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{/$};
>
> I think that 'unless' should be 'if' - if the request is for a 
> directory,
> and if the directory has a trailing slash, set the content handler to 
> be
> perl-script.  I think the above logic demorgans out to
>
>   if ( ! $r->content_type eq DIR_MAGIC_TYPE || $uri !~ m{/$} )
>
> which isn't quite right.  sorry if that is what I wrote before.

Don't think so, it's my fault for not thinking it through (I'm so used 
to telling mod_perl _not_ to handle something! I'll change it to 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 DECLINED;
  }

>>      return DECLINED;
>>  }
>
> returning OK from a fixup handler is probably more idiomatic.

Oh, so that doesn't prevent any others from running? In that case, I'll 
change it to 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 OK;
  }

>> 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.
>
> I think it's clear that you can't handle directories in mason with 
> mod_perl
> 2 until a fixup handler like that is installed - mp2 simply doesn't 
> enter
> into requests for directories at the moment (or so it would seem).

Okay, great, thanks a million!

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
> 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>

-1 is DECLINED, right?

> 
> 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{/$};

I think that 'unless' should be 'if' - if the request is for a directory,
and if the directory has a trailing slash, set the content handler to be
perl-script.  I think the above logic demorgans out to

  if ( ! $r->content_type eq DIR_MAGIC_TYPE || $uri !~ m{/$} )

which isn't quite right.  sorry if that is what I wrote before.

>      return DECLINED;
>  }

returning OK from a fixup handler is probably more idiomatic.

> 
> 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.

I think it's clear that you can't handle directories in mason with mod_perl
2 until a fixup handler like that is installed - mp2 simply doesn't enter
into requests for directories at the moment (or so it would seem).

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
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: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 19, 2004, at 7:53 AM, Larry Leszczynski wrote:

> At apache 1.3 configure time there is "--permute-module" option, which 
> can
> swap module ordering:
>
>    --permute-module=N1:N2
>          on-the-fly permute module 'N1' with module 'N2'
>
> 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 mod_dir,
> e.g.:
>
>    --permute-module=dir:END

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.

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Larry Leszczynski <la...@emailplus.org>.
Hi David -

> > that's the way it would work with apache 1.3, except that
> > ClearModuleList unloads everything, so you now need an AddModule for
> > every module, including mod_cgi, mod_rewrite, mod_auth, etc.
>
> Oh, too bad there isn't a RemoveModule. Then I could just do:
>
>    RemoveModule mod_dir.c
>    AddModule mod_dir.c

At apache 1.3 configure time there is "--permute-module" option, which can
swap module ordering:

   --permute-module=N1:N2
         on-the-fly permute module 'N1' with module 'N2'

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 mod_dir,
e.g.:

   --permute-module=dir:END


HTH,
Larry Leszczynski


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
Thanks for the great reply, Geoff. Sorry I didn't get back to you  
sooner. I've ben snorkeling for the last week. :-)

On May 11, 2004, at 5:19 PM, Geoffrey Young wrote:

> well, not really :)
>
> that's the way it would work with apache 1.3, except that  
> ClearModuleList
> unloads everything, so you now need an AddModule for every module,  
> including
> mod_cgi, mod_rewrite, mod_auth, etc.

Oh, too bad there isn't a RemoveModule. Then I could just do:

   RemoveModule mod_dir.c
   AddModule mod_dir.c

Oh, well!

> outside of that, mod_dir needs to go last, which would give it a higher
> priority.  it's the same as when you do httpd -l to list static  
> modules -
> modules at the bottom of the list get first dibs at the request.   
> you'll see
> mod_perl at the bottom, which is generally what we want but what is  
> causing
> you grief at the moment.

Right, gotcha.

> but outside of those caveats, yes.  giving mod_dir a higher priority  
> will
> mean that apache calls it first for every phase that mod_dir enters.   
> for
> the content generation phase, mod_dir will run and return OK and  
> apache will
> move to the logging phase, leaving mod_perl behind.

Right, I understand now. Too bad mod_dir doesn't run during the fixup  
phase or something. Seems kinda dumb to run it during the response  
phase.

> in apache 2.0 it's a bit different.  when a module registers a hook  
> with
> apache - say mod_rewrite's hook into translation - the module itself  
> tells
> apache the order.  a module can choose to run first, last, or a few  
> other
> things.  this is good for developers but kinda hard on administrators
> because there is absoltely no ability to do the kind of thing in 2.0.

Um, I'm confused. I thought you just said you _could_ do it in 2.0.

> I was
> trying to give mod_perl the ability to dynamically alter its own order  
> and
> it worked for linux but not win32.  one of several threads is here if  
> you're
> interested:
>
>    
> http://marc.theaimsgroup.com/?l=apache-modperl- 
> dev&m=107723862520564&w=2

Doesn't seem like a major loss if you can still do it statically, so to  
speak. I'm not sure how to document this, though; it sounds like  
mod_perl 2 folks will _have_ to use my Apache::Dir module (now  
registered to me--thanks Doug!) if they want the mod_dir behavior,  
while Apache 1 users can use the ClearModules/AddModule solution if  
they'd rather. Or am I missing something?

> ok, the way the content generation phase is dispatched is completely
> different in apache 2.0.  in 1.3 apache only dispatched to registered
> handlers - if r->handler was perl-script then apache called mod_perl,  
> for
> instance.  in 2.0 apache calls _every_ handler, and every hander has  
> the
> responsibility to check r->handler itself.

Oh, so you can more easily chain handlers? That's cool.

> so, in 1.3 mod_perl registered itself for perl-script and  
> DIR_MAGIC_TYPE,
> but in 2.0 there is no registration process.  currently mod_perl only  
> checks
> r->handler for 'perl-script' or 'modperl' and dispatches accordingly.   
> I
> suppose it could check for DIR_MAGIC_TYPE as well, but then to which  
> handler
> to do dispatch to, perl-script or modperl?  the way mod_dir handles  
> this is
> it runs a fixup handler that sets DIR_MAGIC_TYPE if a) it's a  
> directory, and
> b) r->handler wasn't already set.
>
> really, the number of people that actually want to handle directories
> themselves is few (if any), so setting $r->handler('perl-script') from  
> a
> fixup handler isn't that big of a deal.

Well, Mason works this way. If a request comes in for /foo/ and there's  
a file F</foo/dhandler> and Mason is configured to handle directory  
requests, then /foo/dhandler will execute. It will also execute if a  
request comes in for /foo/bar and there is no "bar" directory.  
Requiring that Mason install a fixup handler will probably be somewhat  
of a PITA for Mason users accustomed to a simpler configuration  
(although I guess it's really just one more line in their httpd.conf,  
isn't it? Or, no! Mason can add a fixup handler itself when it loads,  
eh?).

> well, you could have used $r->finfo to save the stat as well, but yes
> DIR_MAGIC_TYPE is probably cleaner :)

Absolutely, thank you.

> well, I didn't look at your code, so I was just guessing.  and it was
> untested :)  but yes, you're right, mod_dir only engages when it's a  
> dir
> with no trailing / (plus a bunch of other subrequest foo I don't really
> understand)

Right, I think all that other stuff has to do with setting up  
DirectoryIndex (usually "index.html") to be used for a directory  
request. But I'm just guessing.

> yeah, I didn't realize you were using 2.0.  the approaches definitely  
> need
> to be different between the two versions, but hopefully everything is  
> a bit
> clearer now.  let me know if you still have questions.

No, I'm not using 2.0. I just want to make sure I can document for  
people how to get the same behavior from the two versions.

Thanks!

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

David Wheeler wrote:
> On May 11, 2004, at 3:24 PM, Geoffrey Young wrote:
> 
>> ClearModuleList/AddModule are not DSO specific - they just shuffle around
>> the order of the internal module list, which is what apache dispatches
>> against at request time.  note that both of these are provide by core,
>> while
>> LoadModule is provided by mod_so.
>>
>>> Does that apply to Apache 1.3 as well as 2.0?
>>
>>
>> unfortunately not.  I'm working on the ability to shuffle module
>> around like
>> that, but I can't get it to work on win32.
> 
> 
> Ah, okay, so just to be clear, with Apache 2, I can do this:
> 
>   ClearModuleList
>   AddModule mod_dir
>   AddModule mod_perl
> 
> And mod_dir will do its thing before things get passed on to any
> mod_perl handlers. Is that right?

well, not really :)

that's the way it would work with apache 1.3, except that ClearModuleList
unloads everything, so you now need an AddModule for every module, including
mod_cgi, mod_rewrite, mod_auth, etc.

outside of that, mod_dir needs to go last, which would give it a higher
priority.  it's the same as when you do httpd -l to list static modules -
modules at the bottom of the list get first dibs at the request.  you'll see
mod_perl at the bottom, which is generally what we want but what is causing
you grief at the moment.

but outside of those caveats, yes.  giving mod_dir a higher priority will
mean that apache calls it first for every phase that mod_dir enters.  for
the content generation phase, mod_dir will run and return OK and apache will
move to the logging phase, leaving mod_perl behind.

in apache 2.0 it's a bit different.  when a module registers a hook with
apache - say mod_rewrite's hook into translation - the module itself tells
apache the order.  a module can choose to run first, last, or a few other
things.  this is good for developers but kinda hard on administrators
because there is absoltely no ability to do the kind of thing in 2.0.  I was
trying to give mod_perl the ability to dynamically alter its own order and
it worked for linux but not win32.  one of several threads is here if you're
interested:

  http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=107723862520564&w=2

> 
>> but directories are really something different.  in mp2 it looks like
>> we'll
>> need to take the approach that mod_dir does in 2.0 - if you want your
>> PerlResponseHandler to be triggered for directories you'll
>> specifically need
>> to set $r->handler('perl-script') in a fixup handler.
> 
> 
> Really?! How come?

ok, the way the content generation phase is dispatched is completely
different in apache 2.0.  in 1.3 apache only dispatched to registered
handlers - if r->handler was perl-script then apache called mod_perl, for
instance.  in 2.0 apache calls _every_ handler, and every hander has the
responsibility to check r->handler itself.

so, in 1.3 mod_perl registered itself for perl-script and DIR_MAGIC_TYPE,
but in 2.0 there is no registration process.  currently mod_perl only checks
r->handler for 'perl-script' or 'modperl' and dispatches accordingly.  I
suppose it could check for DIR_MAGIC_TYPE as well, but then to which handler
to do dispatch to, perl-script or modperl?  the way mod_dir handles this is
it runs a fixup handler that sets DIR_MAGIC_TYPE if a) it's a directory, and
b) r->handler wasn't already set.

really, the number of people that actually want to handle directories
themselves is few (if any), so setting $r->handler('perl-script') from a
fixup handler isn't that big of a deal.


>> yeah, you can probably just check for DIR_MAGIC_TYPE here.
> 
> 
> Cool, saves the expense of the stat!

well, you could have used $r->finfo to save the stat as well, but yes
DIR_MAGIC_TYPE is probably cleaner :)


> Going back to your last message...
> 
>>   - use a fixup handler to override mod_perl settings.  for example:
>>
>>      use Apache::Constants qw(DECLINED DIR_MAGIC_TYPE):
>>      $r->set_handlers(PerlHandler => sub { return DECLINED })
>>        if $r->content_type = DIR_MAGIC_TYPE;
> 
> 
> This assumes that I want to decline a request for a directory every
> time. But I don't; only if there is no "/" at the end. And that's
> effectively what I'm doing with my Apache::Dir module, no?

well, I didn't look at your code, so I was just guessing.  and it was
untested :)  but yes, you're right, mod_dir only engages when it's a dir
with no trailing / (plus a bunch of other subrequest foo I don't really
understand)

> 
> It looks like I could recommend that it be used as PerlFixupHandler,
> though, instead of a PerlHandler (in 1.3).

yeah, I didn't realize you were using 2.0.  the approaches definitely need
to be different between the two versions, but hopefully everything is a bit
clearer now.  let me know if you still have questions.

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 12, 2004, at 4:55 AM, Radoslaw Zielinski wrote:

> Save the expense of the regexp as well. :-)

You underestimate the optimizations of a good regular expression that 
simply checks a character anchored at the end of a string, my friend:

% cat try
#!/usr/bin/perl -w

use strict;
use Benchmark;

my $uri = '/this/that/theother';
my $uri2 = '/this/that/theother';

timethese(10000000, {
     regex => sub {
         return if $uri =~ m{/$};
     },
     regex2 => sub {
         return if $uri2 =~ m{/$};
     },
     substr => sub {
         return if substr($uri, -1, 1) ne '/';
     },
     substr2 => sub {
         return if substr($uri2, -1, 1) ne '/';
     },
});

% try
Benchmark: timing 10000000 iterations of regex, regex2, substr, 
substr2...
      regex:  5 wallclock secs ( 4.26 usr +  0.04 sys =  4.30 CPU) @ 
2325581.40/s (n=10000000)
     regex2:  4 wallclock secs ( 4.35 usr + -0.01 sys =  4.34 CPU) @ 
2304147.47/s (n=10000000)
     substr:  7 wallclock secs ( 7.52 usr +  0.01 sys =  7.53 CPU) @ 
1328021.25/s (n=10000000)
    substr2:  7 wallclock secs ( 7.53 usr +  0.00 sys =  7.53 CPU) @ 
1328021.25/s (n=10000000)

But both are obscenely fast, really. :-)

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Radoslaw Zielinski <ra...@karnet.pl>.
David Wheeler <da...@kineticode.com> [12-05-2004 01:25]:
> On May 11, 2004, at 3:24 PM, Geoffrey Young wrote:
[...]
>> yeah, you can probably just check for DIR_MAGIC_TYPE here.
> Cool, saves the expense of the stat! Here's what I have now:
[...]
>     return DECLINED unless $r->content_type == DIR_MAGIC_TYPE
>       && $r->uri !~ m{/$};
[...]

Save the expense of the regexp as well. :-)

       return DECLINED unless $r->content_type == DIR_MAGIC_TYPE
-        && $r->uri !~ m{/$};
+        && substr($r->uri, -1, 1) ne '/';

-- 
Radosław Zieliński <ra...@karnet.pl>
[ GPG key: http://radek.karnet.pl/ ]

Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 11, 2004, at 3:24 PM, Geoffrey Young wrote:

> ClearModuleList/AddModule are not DSO specific - they just shuffle 
> around
> the order of the internal module list, which is what apache dispatches
> against at request time.  note that both of these are provide by core, 
> while
> LoadModule is provided by mod_so.
>
>> Does that apply to Apache 1.3 as well as 2.0?
>
> unfortunately not.  I'm working on the ability to shuffle module 
> around like
> that, but I can't get it to work on win32.

Ah, okay, so just to be clear, with Apache 2, I can do this:

   ClearModuleList
   AddModule mod_dir
   AddModule mod_perl

And mod_dir will do its thing before things get passed on to any 
mod_perl handlers. Is that right?

> but directories are really something different.  in mp2 it looks like 
> we'll
> need to take the approach that mod_dir does in 2.0 - if you want your
> PerlResponseHandler to be triggered for directories you'll 
> specifically need
> to set $r->handler('perl-script') in a fixup handler.

Really?! How come?

>> What is DIR_MAGIC_TYPE?
>
> the internal content type that Apache sets when it sees that the uri
> resolves to a directory.  I think it's http/unix-directory or 
> something, but
> you can check httpd.h for that.

Ah, okay, thanks!

>> sub handler {
>>     my $r = shift;
>>     return DECLINED unless -d $r->filename && $r->uri !~ m{/$};
>
> yeah, you can probably just check for DIR_MAGIC_TYPE here.

Cool, saves the expense of the stat! Here's what I have now:

sub handler {
     my $r = shift;
     return DECLINED unless $r->content_type == DIR_MAGIC_TYPE
       && $r->uri !~ m{/$};
     my $args = $r->args;
     $r->header_out(Location => $r->uri . '/' . ($args ? "?$args" : ''));
     return HTTP_MOVED_PERMANENTLY;
}

Going back to your last message...

>   - use a fixup handler to override mod_perl settings.  for example:
>
>      use Apache::Constants qw(DECLINED DIR_MAGIC_TYPE):
>      $r->set_handlers(PerlHandler => sub { return DECLINED })
>        if $r->content_type = DIR_MAGIC_TYPE;

This assumes that I want to decline a request for a directory every 
time. But I don't; only if there is no "/" at the end. And that's 
effectively what I'm doing with my Apache::Dir module, no?

It looks like I could recommend that it be used as PerlFixupHandler, 
though, instead of a PerlHandler (in 1.3).

Thanks,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

David Wheeler wrote:
> On May 11, 2004, at 2:40 PM, Geoffrey Young wrote:
> 
>> if all you want is mod_dir's default behavior (before mod_perl would
>> override it) and if you're interested in alternative methods, you
>> could also
>> try some of these.
>>
>>   - use ClearModuleList/AddModule to place mod_dir before mod_perl in the
>> module list, which means loading mod_dir _after_ mod_perl in httpd.conf.
> 
> 
> If they're DSOs. 

ClearModuleList/AddModule are not DSO specific - they just shuffle around
the order of the internal module list, which is what apache dispatches
against at request time.  note that both of these are provide by core, while
LoadModule is provided by mod_so.

> Does that apply to Apache 1.3 as well as 2.0?

unfortunately not.  I'm working on the ability to shuffle module around like
that, but I can't get it to work on win32.

but directories are really something different.  in mp2 it looks like we'll
need to take the approach that mod_dir does in 2.0 - if you want your
PerlResponseHandler to be triggered for directories you'll specifically need
to set $r->handler('perl-script') in a fixup handler.

> 
>>   - use a fixup handler to override mod_perl settings.  for example:
>>
>>      use Apache::Constants qw(DECLINED DIR_MAGIC_TYPE):
>>      $r->set_handlers(PerlHandler => sub { return DECLINED })
>>        if $r->content_type = DIR_MAGIC_TYPE;
> 
> 
> What is DIR_MAGIC_TYPE?

the internal content type that Apache sets when it sees that the uri
resolves to a directory.  I think it's http/unix-directory or something, but
you can check httpd.h for that.

> 
>>   - remove DIR_MAGIC_TYPE from the handler_rec in mod_perl.c and
>> recompile
>>
>> some of these may not be suitable for something like Bricolage
>> support.  but
>> there are options short of rewriting mod_dir in perl.
> 
> 
> Here's all that my Apache::Dir does:
> 
> sub handler {
>     my $r = shift;
>     return DECLINED unless -d $r->filename && $r->uri !~ m{/$};

yeah, you can probably just check for DIR_MAGIC_TYPE here.

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by David Wheeler <da...@kineticode.com>.
On May 11, 2004, at 2:40 PM, Geoffrey Young wrote:

> if all you want is mod_dir's default behavior (before mod_perl would
> override it) and if you're interested in alternative methods, you 
> could also
> try some of these.
>
>   - use ClearModuleList/AddModule to place mod_dir before mod_perl in 
> the
> module list, which means loading mod_dir _after_ mod_perl in 
> httpd.conf.

If they're DSOs. Does that apply to Apache 1.3 as well as 2.0?

>   - use a fixup handler to override mod_perl settings.  for example:
>
>      use Apache::Constants qw(DECLINED DIR_MAGIC_TYPE):
>      $r->set_handlers(PerlHandler => sub { return DECLINED })
>        if $r->content_type = DIR_MAGIC_TYPE;

What is DIR_MAGIC_TYPE?

>   - remove DIR_MAGIC_TYPE from the handler_rec in mod_perl.c and 
> recompile
>
> some of these may not be suitable for something like Bricolage 
> support.  but
> there are options short of rewriting mod_dir in perl.

Here's all that my Apache::Dir does:

sub handler {
     my $r = shift;
     return DECLINED unless -d $r->filename && $r->uri !~ m{/$};
     my $args = $r->args;
     $r->header_out(Location => $r->uri . '/' . ($args ? "?$args" : ''));
     return HTTP_MOVED_PERMANENTLY;
}

It's not everything that mod_dir does.

Regards,

David


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: Apache::Dir

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

David Wheeler wrote:
> G'day.
> 
> I recently had a need to have mod_dir in Apache 1.3 work even when I was
> using a Perl handler. It turns out that mod_dir does its thing during
> the response phase. So I created a quick Perl module to do what I want.
> Here's the description:
> 
>     This simple module is designed to be a partial replacement for the
>     standard Apache mod_dir module. One of the things that module does is
>     to redirect browsers to a directory URL ending in a slash when they
>     request the directory without the slash. Since mod_dir seems do its
>     thing during the Apache response phase, if you use a Perl handler, it
>     won't run. This can be problematic if the Perl handler doesn't likewise
>     take the directory redirecting into account.

if all you want is mod_dir's default behavior (before mod_perl would
override it) and if you're interested in alternative methods, you could also
try some of these.

  - use ClearModuleList/AddModule to place mod_dir before mod_perl in the
module list, which means loading mod_dir _after_ mod_perl in httpd.conf.

  - use a fixup handler to override mod_perl settings.  for example:

     use Apache::Constants qw(DECLINED DIR_MAGIC_TYPE):
     $r->set_handlers(PerlHandler => sub { return DECLINED })
       if $r->content_type = DIR_MAGIC_TYPE;

  - remove DIR_MAGIC_TYPE from the handler_rec in mod_perl.c and recompile

some of these may not be suitable for something like Bricolage support.  but
there are options short of rewriting mod_dir in perl.

HTH

--Geoff




---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org