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]