On Sun 12 Oct 2008, André Warnier wrote:
> <Location /some/url>
>
>    SetHandler jakarta-servlet
>    SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
>
>    PerlXXXHandler My::Module->some_method
>
>    ...
>
> </Location>
>
> ("jakarta-servlet" above means mod_jk --> Tomcat)
> (and PerlXXXHandler being any kind of Perl HTTP Handler running soon
> enough)
>
> The Question :
> Is it possible, in the PerlXXXHandler, on a request-by-request base,
> to "disable" the jakarta-servlet handler, and install the following
> instead
>
>    SetHandler modperl
>    PerlResponseHandler My::Module->some_other_method
>
> ?
>
> I know that I can do something like the above for regular static
> pages, and I use this already :
>    $r->handler('modperl');
>    $r->set_handlers(PerlAuthzHandler => []); # stop authorization
> from running
>    $r->set_handlers(PerlResponseHandler => \&_send_login_form);
>
>
> However, when I try to do the same in a Location like the above, it
> seems that the jakarta-servlet handler runs anyway, and my
> PerlResponseHandler is never called.

Does that piece of code run in a /Perl(PostReadRequest|Trans|
MapToStorage)Handler/ ?

Please, have a look again at the ap_process_request_internal() function 
in httpd-2.x.y/server/request.c. This function implements almost the 
complete request cycle (save PostReadRequest, Response and Log).

Just after ap_run_translate_name(), that is the PerlTransHandler, you'll 
see this piece:

    /* Reset to the server default config prior to running 
map_to_storage
     */
    r->per_dir_config = r->server->lookup_defaults;

    if ((access_status = ap_run_map_to_storage(r))) {
        /* This request wasn't in storage (e.g. TRACE) */
        return access_status;
    }

    /* Rerun the location walk, which overrides any map_to_storage 
config.
     */
    if ((access_status = ap_location_walk(r))) {
        return access_status;
    }

    /* Only on the main request! */
    if (r->main == NULL) {
        if ((access_status = ap_run_header_parser(r))) {
            return access_status;
        }
    }
...

The line "r->per_dir_config = r->server->lookup_defaults;" resets all 
request specific configurations applied so far. After that line the 
request is configured as if no Directory/Location or other container 
were present in your httpd.conf. Next comes MapToStorage. Here 
Directory, DirectoryMatch, Files and FilesMatch containers are applied 
to the request. Then, and this is what I think hits you, comes an 
ap_location_walk. Here Location containers are applied. So, your 
SetHandler inside the Location overrides any $r->handler seen before.

After the ap_location_walk comes the PerlHeaderParserHandler. But it is 
skipped for subrequests. A further examination will show you that the 
next phase that is run by all requests is the PerlTypeHandler just 
before Fixup. So, move your "$r->handler('modperl');" to one of those 
and it will work. I prefer Fixup but that is based only on the fact 
that it is documented as do-what-you-want phase. There are directives 
that change the handler in the type-checker phase. In fact the 
AddHandler directive works that way. Mod_mime looks at the file 
extension and adjusts the handler, e.g "AddHandler cgi-script .pl". So 
using Fixup your module is the last to kick in.

To carry state around use pnotes, notes or subprocess_env.

Torsten

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

Reply via email to