On Sun 12 Oct 2008, André Warnier wrote:
> In an attempt at being clever, I put the following code in the
> handler :
>
> unless ($r->is_initial_req) {
> if (defined $r->prev) {
> # we are in a subrequest. Just copy user from main
> request. $r->user( $r->prev->user );
> }
> # Also disable authorization phase
> $r->set_handlers(PerlAuthzHandler => undef);
> return OK;
> }
You have to distinguish between subrequests and internal redirects. The
former result from $r->lookup_uri, $r->lookup_file or similar (there
are a few more such functions in the C API) and internal redirects that
result from $r->internal_redirect (internal_fast_redirect() is not as
the name suggests an internal redirect but simply overrides the current
request). Subrequests are used for example by mod_rewrite, mod_include,
mod_negotiation to look for some characteristics of a document and
perhaps pull it in (run() it). Internal redirects are used in mod_cgi
when the CGI output indicates a status 200 (HTTP_OK) but also contains
a Location header. But the main usage of internal redirects is the
ErrorDocument.
Now, is_initial_req() checks if the current $r is the result of a
subrequest or the result of a internal redirect and returns false if
so. prev() returns the parent request if the current $r is the result
of an internal redirect and main() returns the main request if the
current $r is a subrequest. So, your code checks only for internal
redirects (ErrorDocument).
Now, have a look at httpd-2.x.y/server/request.c around line 170. You'll
see this piece of code:
/* Skip authn/authz if the parent or prior request passed the
* authn/authz,
* and that configuration didn't change (this requires
* optimized _walk()
* functions in map_to_storage that use the same merge results given
* identical input.) If the config changes, we must re-auth.
*/
if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
r->user = r->main->user;
r->ap_auth_type = r->main->ap_auth_type;
}
else if (r->prev && (r->prev->per_dir_config == r->per_dir_config))
{
r->user = r->prev->user;
r->ap_auth_type = r->prev->ap_auth_type;
}
else {
switch (ap_satisfies(r)) {
case SATISFY_ALL:
case SATISFY_NOSPEC:
if ((access_status = ap_run_access_checker(r)) != 0) {
return decl_die(access_status, "check access", r);
...
You see, you are not the first who had had the idea of reusing an
established identity. If your subreq or internal redirect hits the same
Location or Directory container the AAA phases are completely skipped.
Maybe this is enough optimization if you shift a few directives around
in your httpd.conf.
If not, the code above shows you how to do it. But you must ask yourself
if it really is valid to reuse the identity. I believe, you can safely
inherit the identity from $r->main or $r->prev but you must not skip
the other 2 A's. If you can't it would mean you have one realm of
identities for the main request and another for the subreq. That, I'd
say, is a configuration error.
> The idea being that if we are in a sub-request, there is no point in
> authenticating/authorizing it again, since the main request should
> already do that, right ? Optimisation..
>
> Now the above works very nicely, except in the case where, before
> this handler gets called, there is an intervention by mod_rewrite. It
> seems as if mod_rewrite makes the above fail, even when the rewrite
> condition does not apply and the URL is considered as a
> "pass-through".
>
> I suspect that it is because mod_rewrite, no matter what, invoques
> the original (or modified) URL as a sub-request of the original
> request. This would cause the above to fail, because in such a case,
> the above conditional code would be invoked, but there is no
> $r->prev->user to be copied.
mod_rewrite doesn't make subrequests if not asked to. I know only of 2
ways to have mod_rewrite perform a subreq: %{LA-U:variable}
and %{LA-F:variable} in a RewriteCond.
Torsten
--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]