Re: setHandler question
Ryan Gies <[email protected]>
| Newsgroups | gmane.comp.apache.mod-perl |
|---|---|
| Message-ID | <[email protected]> |
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.