You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by André Warnier <aw...@ice-sa.com> on 2012/12/14 14:52:28 UTC

setHandler question

Hi.

Quite a while ago (2008), this discussion on the list :

http://marc.info/?l=apache-modperl&m=122399752819709&w=2

was about how to, within a PerlAuthenHandler, override the ResponseHandler which would 
normally kick in later in the cycle, and force it to be mod_perl and a specific (other) 
PerlresponseHandler.

The general idea is like :

if (some_condition) {

    $r->handler('modperl');
    $r->set_handlers(PerlResponseHandler => \&_my_response_handler);
}

or even :

$r->set_handlers(PerlResponseHandler => \&_my_response_handler);
$r->set_handlers(PerlFixupHandler => sub { $_[0]->handler('modperl') } );

and generally speaking it works.
Only, sometimes it doesn't, and Apache proceeds to use the previously-configured response 
handler no matter what.

Then there was a hint that, in addition to the above, one might need to also set or clear 
something in the $r->finfo structure, to (as I, with my limited knowledge understand it) 
tell Apache that we really know what we are doing, and really want to override what it 
already knows about the final destination.

This "thing" to set in the $r->finfo() being Apache2::Const::OR_FILEINFO or thereabouts.

And an example was even given in the thread, as :

   $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO)

Only, here I have already set the Handler, and I would merely want to try just to set the 
above flag.
So how would I do that ?

I do not see a way to pass this argument in $r->handler().
I see in the doc this : http://perl.apache.org/docs/2.0/api/Apache2/RequestRec.html#C_finfo_

but I do not really understand the example given.

I suppose that in the end I will want to do something like this :

my $finfo = $r->finfo();
# do something to $finfo to set the flag
$r->finfo($finfo);
$r->handler('modperl');
$r->set_handlers(PerlResponseHandler => \&_my_response_handler);

but how do I "do something to $finfo" ?

Or am I totally off-track here ?

TIA

Re: setHandler question

Posted by Ryan Gies <ry...@livesite.net>.
On 12/14/2012 3:29 PM, André Warnier wrote:
> Ryan Gies wrote:
>> On 12/14/2012 8:52 AM, André Warnier wrote:
>>> I suppose that in the end I will want to do something like this :
>>>
>>> my $finfo = $r->finfo();
>>> # do something to $finfo to set the flag
>>> $r->finfo($finfo);
>>> $r->handler('modperl');
>>> $r->set_handlers(PerlResponseHandler => \&_my_response_handler);
>>>
>>> but how do I "do something to $finfo" ?
>>>
>>> Or am I totally off-track here ?
>>>
>>> TIA
>> For what it's worth, I have consistent success in using $r->finfo to 
>> tell Apache the final destination. In the case that $you_want_to_hook 
>> (below) is false, Apache will also serve the intended file. The 
>> timing used is:
>>
>> PerlMapToStorageHandler
>>
>>   $r->filename($path); # where $path is an absolute file-system path
>>   $r->finfo(APR::Finfo::stat($path, APR::Const::FINFO_NORM, $r->pool));
>>   return Apache2::Const::OK;
>>
>> PerlFixupHandler
>>
>>   if ($you_want_to_hook) {
>>     $r->push_handlers(PerlResponseHandler => \&_response_handler);
>>     $r->handler('modperl');
>>     return Apache2::Const::OK;
>>   }
>>
>
> Let me explain better what I am looking for :
>
> <LocationMatch "/IIS_app/(.*)$">
>   PerlAuthenHandler SLC->authenticate
>   PerlAuthzHandler SLC->authorize
>   PerlSetVar SLC_login_page "/public/login.html"
>   ...
>   ProxyPassMatch http://localhost:8800/$1
> </LocationMatch>
>
> In other words,
> - Apache+mod_perl is acting as a reverse proxy for an application 
> running under IIS on the same server
> - but this IIS application requires a special HTTP header to 
> authenticate the user
> - In the Location above, the PerlAuthenHandler checks if the user is 
> authenticated.
>     - If yes, it adds the required HTTP header to the request, and 
> then a few steps later the proxying happens to IIS, and that's fine.
>     - If not, it sends back a login page.
>
> What I want to do refers to the "sends back a login page".
> In case the user is not authenticated, I do /not/ want Apache to proxy 
> the call to IIS.
> I want to reset the response handler so that it is no longer 
> mod_proxy, but mod_perl, and my own PerlResponseHandler (which sends 
> back the login page "/public/login.html", after munching on it).
> But what happens is that the proxying runs anyway, and the request 
> ends up in IIS, but without the authentication header.
> That's what I want to avoid.
>
> In the PerlAuthenHandler, I already do this :
>
> if ($not_authenticated)
> {
>    $r->handler('modperl'); # (1)
>    $r->set_handlers(PerlResponseHandler => \&_my_send_login_handler); 
> # (2)
>    $r->set_handlers(PerlFixupHandler => sub { 
> $_[0]->handler('modperl') } ); # (3)
>    return Apache2::Const::OK;
> }
>
> But that is apparently not enough.  It is still (later) proxying the 
> request to IIS.
> So it is apparently ignoring the line
>    $r->handler('modperl'); # (1)
>
> What am I missing ? (as another way of phrasing the initial question)
>
> I am led to believe that it has to do with the "map-to-storage" phase, 
> which has already happened by the time the PerlAuthenHandler runs, and 
> that in order to completely override the mod_proxy response handler, I 
> need to set/reset some flag(s).
> I'd like (if possible) to do that "dynamically" in the 
> PerlAuthenHandler, without having to configure an extra 
> PerlMapToStorageHandler in my configuration for that Location.
>
> (In the above, (1) and (3) are probably the same thing, with (3) 
> happening later and having maybe a better chance. But it's still not 
> working.
>
> Would these 2 lines :
>
> >   $r->filename($path); # where $path is an absolute file-system path
> >   $r->finfo(APR::Finfo::stat($path, APR::Const::FINFO_NORM, $r->pool));
>
> added to the above current code, do the trick ?
I would need to duplicate your scenario, setting up a ProxyPass 
situation such as you've described, to help answer that. I do however 
suspect that if you change the approach to do something like this:

   my $login_page = '/public/login.html';
   $r->add_config(["ErrorDocument 401 $login_page"]);
   $r->err_headers_out->add('WWW-Authenticate' => 'Web'); # Required header
   return Apache2::Const::AUTH_REQUIRED;

That the ProxyPass will not happen. You would then munch on 
/public/login.html separately, as a sub-request.

Re: setHandler question

Posted by André Warnier <aw...@ice-sa.com>.
Rafael Caceres wrote:
...

> 
> What you want works for me when reverse proxying to Tomcat or another Apache by adding a
> require valid-user inside the LocationMatch
> 
Thanks for your interest.
That would indeed work if my authentication sub returned an "auth required" when the 
request is not authenticated.  But right now it doesn't.  Instead, it returns OK, but 
(tries to) set up a special ResponseHandler to return a login page.
That is what failed previously, as Apache didn't seem to care and mod_proxy was still 
responding to the request.
But that is now solved, and it works as expected, see previous messages in thread.

André



Re: setHandler question

Posted by Rafael Caceres <rc...@aasa.com.pe>.
Andre,

Ryan Gies wrote:
> On 12/14/2012 8:52 AM, André Warnier wrote:
>> I suppose that in the end I will want to do something like this :
>>
>> my $finfo = $r->finfo();
>> # do something to $finfo to set the flag
>> $r->finfo($finfo);
>> $r->handler('modperl');
>> $r->set_handlers(PerlResponseHandler => \&_my_response_handler);
>>
>> but how do I "do something to $finfo" ?
>>
>> Or am I totally off-track here ?
>>
>> TIA
> For what it's worth, I have consistent success in using $r->finfo to 
> tell Apache the final destination. In the case that $you_want_to_hook 
> (below) is false, Apache will also serve the intended file. The timing 
> used is:
> 
> PerlMapToStorageHandler
> 
>   $r->filename($path); # where $path is an absolute file-system path
>   $r->finfo(APR::Finfo::stat($path, APR::Const::FINFO_NORM, $r->pool));
>   return Apache2::Const::OK;
> 
> PerlFixupHandler
> 
>   if ($you_want_to_hook) {
>     $r->push_handlers(PerlResponseHandler => \&_response_handler);
>     $r->handler('modperl');
>     return Apache2::Const::OK;
>   }
> 

Let me explain better what I am looking for :

<LocationMatch "/IIS_app/(.*)$">
   PerlAuthenHandler SLC->authenticate
   PerlAuthzHandler SLC->authorize
   PerlSetVar SLC_login_page "/public/login.html"
   ...
   ProxyPassMatch http://localhost:8800/$1
</LocationMatch>

In other words,
- Apache+mod_perl is acting as a reverse proxy for an application running under IIS on the 
same server
- but this IIS application requires a special HTTP header to authenticate the user
- In the Location above, the PerlAuthenHandler checks if the user is authenticated.
     - If yes, it adds the required HTTP header to the request, and then a few steps later 
the proxying happens to IIS, and that's fine.
     - If not, it sends back a login page.

What I want to do refers to the "sends back a login page".
In case the user is not authenticated, I do /not/ want Apache to proxy the call to IIS.
I want to reset the response handler so that it is no longer mod_proxy, but mod_perl, and 
my own PerlResponseHandler (which sends back the login page "/public/login.html", after 
munching on it).
But what happens is that the proxying runs anyway, and the request ends up in IIS, but 
without the authentication header.
That's what I want to avoid.

What you want works for me when reverse proxying to Tomcat or another Apache by adding a
require valid-user inside the LocationMatch

Regards,
Rafael Caceres

Re: setHandler question

Posted by André Warnier <aw...@ice-sa.com>.
Ryan Gies wrote:
> On 12/14/2012 8:52 AM, André Warnier wrote:
>> I suppose that in the end I will want to do something like this :
>>
>> my $finfo = $r->finfo();
>> # do something to $finfo to set the flag
>> $r->finfo($finfo);
>> $r->handler('modperl');
>> $r->set_handlers(PerlResponseHandler => \&_my_response_handler);
>>
>> but how do I "do something to $finfo" ?
>>
>> Or am I totally off-track here ?
>>
>> TIA
> For what it's worth, I have consistent success in using $r->finfo to 
> tell Apache the final destination. In the case that $you_want_to_hook 
> (below) is false, Apache will also serve the intended file. The timing 
> used is:
> 
> PerlMapToStorageHandler
> 
>   $r->filename($path); # where $path is an absolute file-system path
>   $r->finfo(APR::Finfo::stat($path, APR::Const::FINFO_NORM, $r->pool));
>   return Apache2::Const::OK;
> 
> PerlFixupHandler
> 
>   if ($you_want_to_hook) {
>     $r->push_handlers(PerlResponseHandler => \&_response_handler);
>     $r->handler('modperl');
>     return Apache2::Const::OK;
>   }
> 

Let me explain better what I am looking for :

<LocationMatch "/IIS_app/(.*)$">
   PerlAuthenHandler SLC->authenticate
   PerlAuthzHandler SLC->authorize
   PerlSetVar SLC_login_page "/public/login.html"
   ...
   ProxyPassMatch http://localhost:8800/$1
</LocationMatch>

In other words,
- Apache+mod_perl is acting as a reverse proxy for an application running under IIS on the 
same server
- but this IIS application requires a special HTTP header to authenticate the user
- In the Location above, the PerlAuthenHandler checks if the user is authenticated.
     - If yes, it adds the required HTTP header to the request, and then a few steps later 
the proxying happens to IIS, and that's fine.
     - If not, it sends back a login page.

What I want to do refers to the "sends back a login page".
In case the user is not authenticated, I do /not/ want Apache to proxy the call to IIS.
I want to reset the response handler so that it is no longer mod_proxy, but mod_perl, and 
my own PerlResponseHandler (which sends back the login page "/public/login.html", after 
munching on it).
But what happens is that the proxying runs anyway, and the request ends up in IIS, but 
without the authentication header.
That's what I want to avoid.

In the PerlAuthenHandler, I already do this :

if ($not_authenticated)
{
    $r->handler('modperl'); # (1)
    $r->set_handlers(PerlResponseHandler => \&_my_send_login_handler); # (2)
    $r->set_handlers(PerlFixupHandler => sub { $_[0]->handler('modperl') } ); # (3)
    return Apache2::Const::OK;
}

But that is apparently not enough.  It is still (later) proxying the request to IIS.
So it is apparently ignoring the line
    $r->handler('modperl'); # (1)

What am I missing ? (as another way of phrasing the initial question)

I am led to believe that it has to do with the "map-to-storage" phase, which has already 
happened by the time the PerlAuthenHandler runs, and that in order to completely override 
the mod_proxy response handler, I need to set/reset some flag(s).
I'd like (if possible) to do that "dynamically" in the PerlAuthenHandler, without having 
to configure an extra PerlMapToStorageHandler in my configuration for that Location.

(In the above, (1) and (3) are probably the same thing, with (3) happening later and 
having maybe a better chance. But it's still not working.

Would these 2 lines :

 >   $r->filename($path); # where $path is an absolute file-system path
 >   $r->finfo(APR::Finfo::stat($path, APR::Const::FINFO_NORM, $r->pool));

added to the above current code, do the trick ?

Re: setHandler question

Posted by Ryan Gies <ry...@livesite.net>.
On 12/14/2012 8:52 AM, André Warnier wrote:
> I suppose that in the end I will want to do something like this :
>
> my $finfo = $r->finfo();
> # do something to $finfo to set the flag
> $r->finfo($finfo);
> $r->handler('modperl');
> $r->set_handlers(PerlResponseHandler => \&_my_response_handler);
>
> but how do I "do something to $finfo" ?
>
> Or am I totally off-track here ?
>
> TIA
For what it's worth, I have consistent success in using $r->finfo to 
tell Apache the final destination. In the case that $you_want_to_hook 
(below) is false, Apache will also serve the intended file. The timing 
used is:

PerlMapToStorageHandler

   $r->filename($path); # where $path is an absolute file-system path
   $r->finfo(APR::Finfo::stat($path, APR::Const::FINFO_NORM, $r->pool));
   return Apache2::Const::OK;

PerlFixupHandler

   if ($you_want_to_hook) {
     $r->push_handlers(PerlResponseHandler => \&_response_handler);
     $r->handler('modperl');
     return Apache2::Const::OK;
   }

Re: setHandler question

Posted by André Warnier <aw...@ice-sa.com>.
André Warnier wrote:
> Torsten Förtsch wrote:
>> On 12/15/2012 01:30 PM, André Warnier wrote:
>>> And somehow the $r->add_config() looks a bit like a roundabout way of
>>> achieving what I want.  If I can, kind of, "stuff" an additional
>>> SetHandler configuration directive into the Apache configuration for my
>>> request, telling Apache "now do as if the <Location> contained a
>>> SetHandler directive", then why does the simpler $r->setHandler() not
>>> work ?
>>
>> Perhaps that was the reason for ->add_config instead of ->handler. The
>> former sets the handler at the point in the request cycle when
>> SetHandler works, which I think is fixup. The latter acts at the point
>> of the call.
>>
>> The point here is that modperl's PerlFixupHandler is registered with
>> APR_HOOK_REALLY_FIRST meaning it is called before (almost) all other
>> handlers. So, even if you use ->handler to set the handler to modperl
>> another module may decide to override your decision.
>>
>> There is another glitch with mod_proxy here. A normal response handler
>> checks the content of ->handler to see if it is responsible to generate
>> the response. Not so mod_proxy. It relies on ->proxyreq:
>>
>> In fact, where other modules do something like this to decide if they
>> are to generate the response:
>>
>>     if(strcmp(r->handler, CGI_MAGIC_TYPE) &&
>>        strcmp(r->handler, "cgi-script"))
>>         return DECLINED;
>>
>> mod_proxy does this:
>>
>>     /* is this for us? */
>>     if (!r->proxyreq || !r->filename ||
>>         strncmp(r->filename, "proxy:", 6) != 0)
>>         return DECLINED;
>>
>> I think what you want to do is to reconfigure a request previously set
>> up to be handled by mod_proxy, right? So, in that case you have to
>> either reset $r->proxyreq to 0 or reset $r->filename to NULL or to
>> change $r->filename to not start with "proxy:".
>>
> 
> YES, resetting $r->filename() does it.
> Just for the sake of it, I forced it to the URL of my login page(*), and 
> it doesn't proxy anymore.
> Thanks.
> Now I'll study the info above, to really try to understand what's going on.
> 
> 
> (*) which I know is wrong, but since I retrieve the login page myself in 
> the ResponseHandler, I figured it didn't matter.
> 

I also tried the following sequence, and it works just as well :

	$r->proxyreq(Apache2::Const::PROXYREQ_NONE);
	$r->handler('modperl');
	$r->set_handlers(PerlResponseHandler => \&_send_login_form);

And I also tried :

	my $dest = $r->filename();
	$dest =~ s/^proxy://;
	$r->filename($dest);
	# $r->proxyreq(Apache2::Const::PROXYREQ_NONE);
	$r->handler('modperl');
	$r->set_handlers(PerlResponseHandler => \&_send_login_form);

and it also works (with or without the commented $r->proxyreq)

I am in the meantime discussing the same thing with Rainer Jung (developer of the mod_jk 
Apache/Tomcat connector module), because in terms of functionality, mod_jk is similar to 
mod_proxy.  I hope to be able to write some code in the end which covers all cases at once.

And anyway this is fun. Doing things with mod_perl provides a lot of insights in terms of 
how Apache httpd works.

Thanks very much for the help.

André


Re: setHandler question

Posted by André Warnier <aw...@ice-sa.com>.
Torsten Förtsch wrote:
> On 12/15/2012 01:30 PM, André Warnier wrote:
>> And somehow the $r->add_config() looks a bit like a roundabout way of
>> achieving what I want.  If I can, kind of, "stuff" an additional
>> SetHandler configuration directive into the Apache configuration for my
>> request, telling Apache "now do as if the <Location> contained a
>> SetHandler directive", then why does the simpler $r->setHandler() not
>> work ?
> 
> Perhaps that was the reason for ->add_config instead of ->handler. The
> former sets the handler at the point in the request cycle when
> SetHandler works, which I think is fixup. The latter acts at the point
> of the call.
> 
> The point here is that modperl's PerlFixupHandler is registered with
> APR_HOOK_REALLY_FIRST meaning it is called before (almost) all other
> handlers. So, even if you use ->handler to set the handler to modperl
> another module may decide to override your decision.
> 
> There is another glitch with mod_proxy here. A normal response handler
> checks the content of ->handler to see if it is responsible to generate
> the response. Not so mod_proxy. It relies on ->proxyreq:
> 
> In fact, where other modules do something like this to decide if they
> are to generate the response:
> 
>     if(strcmp(r->handler, CGI_MAGIC_TYPE) &&
>        strcmp(r->handler, "cgi-script"))
>         return DECLINED;
> 
> mod_proxy does this:
> 
>     /* is this for us? */
>     if (!r->proxyreq || !r->filename ||
>         strncmp(r->filename, "proxy:", 6) != 0)
>         return DECLINED;
> 
> I think what you want to do is to reconfigure a request previously set
> up to be handled by mod_proxy, right? So, in that case you have to
> either reset $r->proxyreq to 0 or reset $r->filename to NULL or to
> change $r->filename to not start with "proxy:".
> 

YES, resetting $r->filename() does it.
Just for the sake of it, I forced it to the URL of my login page(*), and it doesn't proxy 
anymore.
Thanks.
Now I'll study the info above, to really try to understand what's going on.


(*) which I know is wrong, but since I retrieve the login page myself in the 
ResponseHandler, I figured it didn't matter.


Re: setHandler question

Posted by Torsten Förtsch <to...@gmx.net>.
On 12/15/2012 01:30 PM, André Warnier wrote:
> And somehow the $r->add_config() looks a bit like a roundabout way of
> achieving what I want.  If I can, kind of, "stuff" an additional
> SetHandler configuration directive into the Apache configuration for my
> request, telling Apache "now do as if the <Location> contained a
> SetHandler directive", then why does the simpler $r->setHandler() not
> work ?

Perhaps that was the reason for ->add_config instead of ->handler. The
former sets the handler at the point in the request cycle when
SetHandler works, which I think is fixup. The latter acts at the point
of the call.

The point here is that modperl's PerlFixupHandler is registered with
APR_HOOK_REALLY_FIRST meaning it is called before (almost) all other
handlers. So, even if you use ->handler to set the handler to modperl
another module may decide to override your decision.

There is another glitch with mod_proxy here. A normal response handler
checks the content of ->handler to see if it is responsible to generate
the response. Not so mod_proxy. It relies on ->proxyreq:

In fact, where other modules do something like this to decide if they
are to generate the response:

    if(strcmp(r->handler, CGI_MAGIC_TYPE) &&
       strcmp(r->handler, "cgi-script"))
        return DECLINED;

mod_proxy does this:

    /* is this for us? */
    if (!r->proxyreq || !r->filename ||
        strncmp(r->filename, "proxy:", 6) != 0)
        return DECLINED;

I think what you want to do is to reconfigure a request previously set
up to be handled by mod_proxy, right? So, in that case you have to
either reset $r->proxyreq to 0 or reset $r->filename to NULL or to
change $r->filename to not start with "proxy:".

Torsten

Re: setHandler question

Posted by André Warnier <aw...@ice-sa.com>.
Torsten Förtsch wrote:
> On 12/14/2012 02:52 PM, André Warnier wrote:
>> Or am I totally off-track here ?
> 
> I think yes, you are confused by the similarity of "finfo" and
> "OR_FILEINFO".

Yes, I was. Thanks for setting me right.

> 
> The finfo part of $r is simply a data structure that represents the
> metadata of a file on the filesystem such as modification dates, access
> rights, the size and whether it is a regular file, directory, socket or
> something else.
> 
> A standard request for a static file in Apache works as follows. In the
> MapToStorage phase the request URI is mapped to a file (or directory) on
> the filesystem (by means of DocumentRoot, Alias and the like). Then also
> in the MapToStorage phase Apache performs a stat(2) call on the resolved
> file name. The result is stored in $r->finfo.
> 

Ok. Then, in my case I have

<LocationMatch "/IIS_app/(.*)$">
   PerlAuthenHandler SLC->authenticate
   PerlAuthzHandler SLC->authorize
   PerlSetVar SLC_login_page "/public/login.html"
   ...
   ProxyPassMatch http://localhost:8800/$1
</LocationMatch>

"/IIS_app/" does not map to anything on the filesystem.
I guess then that $r->finfo should not contain anything, or at least nothing related to a 
disk file.  And neither $r->filename();

> Then in the response phase the information stored in finfo is used to
> set up the Content-Length header as well as the cache control headers
> like Etag and Last-Modified.
> 

So nothing here that is relevant, as these headers would normally be generated by IIS.

> OR_FILEINFO on the other hand is simply a flag that represents the
> "FileInfo" flag in the "AllowOverride" directive:
> 
>   http://httpd.apache.org/docs/2.2/mod/core.html#allowoverride
> 
> Modperl's $r->add_config acts more or less like a .htaccess file. In
> this context the "SetHandler" directive needs "AllowOverride FileInfo"
> to be in effect. See
> 
>   http://httpd.apache.org/docs/2.2/mod/core.html#sethandler
> 
> Unlike a .htaccess file, $r->add_config expects the override bits as the
> next parameter after the list of configuration directives.
> 
> So, to be able to set the handler by means of
> 
>   $r->add_config(['SetHandler ...'])
> 
> you have to pass along a set of override bits that includes OR_FILEINFO.
> That means for example
> 
>   $r->add_config(['SetHandler ...'], OR_FILEINFO)
> 
> or even
> 
>   $r->add_config(['SetHandler ...'], ~0)
> 
> since ~0 is an integer with all bits set.
> 
> I can't remember why I hinted at $r->add_config instead of
> $r->handler('newhandler') at the time of the first discussion. Perhaps
> there was a reason (like the wrong request phase), perhaps I had a blackout.
> 
Perhaps. But you are forgiven, since I think that it was with the best of intentions anyway.

My basic question is that I am setting
$r->handler('modperl');
in the PerlAuthenHandler above, and neither Apache nor mod_perl complain.  But it does not 
stop Apache from proxying the call anyway.
Even if (as per one of your earlier suggestions), I do (or repeat) this 
$r->handler('modperl'); in a Fixup handler.

Why is that ?
Does mod_proxy somehow have still some "priority" as compared to the mod_perl handler ?
Does mod_proxy do something earlier in the cycle that causes the $r->handler() to 
(silently) have no effect later ?

> I hope you understand now that "OR_FILEINFO" and "finfo" are completely
> unrelated things. The only thing they have in common is a certain
> similarity in their names.

Yes, I understand that now.  My confusion came from imagining that the MapToStorage phase 
(subverted ny mod_proxy) might put something in the $r->finfo, that would cause the effect 
later.



I know that I can do this via either an ErrorDocument, or via the call to
$r->add_config(['SetHandler ...'], OR_FILEINFO).

But my current code is not really suited to do it via an ErrorDocument.

And somehow the $r->add_config() looks a bit like a roundabout way of achieving what I 
want.  If I can, kind of, "stuff" an additional SetHandler configuration directive into 
the Apache configuration for my request, telling Apache "now do as if the <Location> 
contained a SetHandler directive", then why does the simpler $r->setHandler() not work ?



Re: setHandler question

Posted by Torsten Förtsch <to...@gmx.net>.
On 12/14/2012 02:52 PM, André Warnier wrote:
> Or am I totally off-track here ?

I think yes, you are confused by the similarity of "finfo" and
"OR_FILEINFO".

The finfo part of $r is simply a data structure that represents the
metadata of a file on the filesystem such as modification dates, access
rights, the size and whether it is a regular file, directory, socket or
something else.

A standard request for a static file in Apache works as follows. In the
MapToStorage phase the request URI is mapped to a file (or directory) on
the filesystem (by means of DocumentRoot, Alias and the like). Then also
in the MapToStorage phase Apache performs a stat(2) call on the resolved
file name. The result is stored in $r->finfo.

Then in the response phase the information stored in finfo is used to
set up the Content-Length header as well as the cache control headers
like Etag and Last-Modified.

OR_FILEINFO on the other hand is simply a flag that represents the
"FileInfo" flag in the "AllowOverride" directive:

  http://httpd.apache.org/docs/2.2/mod/core.html#allowoverride

Modperl's $r->add_config acts more or less like a .htaccess file. In
this context the "SetHandler" directive needs "AllowOverride FileInfo"
to be in effect. See

  http://httpd.apache.org/docs/2.2/mod/core.html#sethandler

Unlike a .htaccess file, $r->add_config expects the override bits as the
next parameter after the list of configuration directives.

So, to be able to set the handler by means of

  $r->add_config(['SetHandler ...'])

you have to pass along a set of override bits that includes OR_FILEINFO.
That means for example

  $r->add_config(['SetHandler ...'], OR_FILEINFO)

or even

  $r->add_config(['SetHandler ...'], ~0)

since ~0 is an integer with all bits set.

I can't remember why I hinted at $r->add_config instead of
$r->handler('newhandler') at the time of the first discussion. Perhaps
there was a reason (like the wrong request phase), perhaps I had a blackout.

I hope you understand now that "OR_FILEINFO" and "finfo" are completely
unrelated things. The only thing they have in common is a certain
similarity in their names.

Torsten