On Tue 14 Oct 2008, André Warnier wrote:
> At this moment, I cannot see clearly how the ErrorDocument solution
> would allow me to send back a login page created dynamically, as I
> need to do.  I will look it up, but as a definitive solution for the
> time being I would prefer the $r->internal_redirect method, where I
> can see more clearly how to do this.

<Location /secured>
PerlAuthenHandler "sub { \
  return Apache2::Const::FORBIDDEN unless ...;
}"
ErrorDocument 403 /login
</Location>

<Location /login>
SetHandler modperl
# you still have to supply a login_form function that expects a
# $r object.
PerlResponseHandler "sub { \
  my $r=shift; \
  $r->content_type('text/html'); \
  $r->print(login_form($r->prev));
  return Apache2::Const::OK;
}"
</Location>

Your A-handler returns 403. Instead of sending the standard FORBIDDEN 
page to the browser apache catches the error because of the 
ErrorDocument directive. "/login" looks like an URI. Hence apache will 
perform an internal redirect to it. "/login" is configured in the 
normal modperl-way.

The browser will see an HTTP status of 403 (it will also be logged as 
403). But the message sent along will be the output of &login_form. And 
that is what the user will see. &login_form has access to the original 
request. So, it can pass the original URI in a hidden field.

See also http://httpd.apache.org/docs/2.2/mod/core.html#errordocument

Instead of 403 you can also use 401 if you want to use 
http-authentication. That is the user will see a browser generated 
password box. But I doubt that is what you want.

> But I still have some (hopefully) last questions, if you would be so
> kind :
>
> As I understand this, the internal_redirect() basically stops the
> current request, and replaces it in-place by a totally new request,
> except that in that new request, $r->prev will be set to the
> (original) request that did the redirect, right ?

Yes. Best if you return OK from the current handler right after the 
$r->internal_redirect line.

> (So in the new request, I can still access the pnotes set by the
> original request, via $r->prev->pnotes()).

Yes.

> For this new request, the cycle restarts right at the beginning, and
> runs through all the steps just as if this was a main request. Right
> ?

AAA are possibly skipped as I mentioned before.

> Are there any other significant differences between this new request
> and the previous one that I should be very aware of (in a
> mod_perl/AAA context) ?

You'll find some, ;-)

> One thing I do not really understand, is what happens to the original
> request, when it issues a call to $r->internal_redirect().
> Does the original request still run to completion, or does it "abort"
> right there ?

I think you'll see the original request again in the logging phase.

> Does Apache still return something to the browser for the original
> request, or is that completely replaced by whatever the new
> (redirected) request produces ?

No, not unless you have sent something prior to the internal_redirect.

> After the call to $r->internal_redirect(), should the original
> request still do something ? (like return Apache2::Const::?????) ?

OK, see 
http://perl.apache.org/docs/2.0/api/Apache2/SubRequest.html#C_internal_redirect_

> P.S.
> I have downloaded the Apache source, and looked at the code within
> httpd-2.x.y/server/request.c, but it is still a bit obscure to me,
> except in a very general sense.  I kind of approximately follow the
> steps, but do not always understand aspects like why it re-does
> directory walks at several stages, nor can I see at all where
> mod_perl plugs in to that code.

great! Many treasures are hidden there.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]

Reply via email to