sethandlers question
Hi. Still around a new perl AAA module I'm writing, a question : If I have a Location like so : SetHandler jakarta-servlet SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk PerlXXXHandler My::Module->some_method ... ("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. The reason I want to do it that way, is that it allows me, in the substituted PerlResponseHandler, to do some stuff to the login page that I send, which would be more complicated to do via a simple redirect. Or ? (One thing I have not tried (nor researched) e.g., is to see if I can install both modperl and the jakarta-servlet as handlers, and disable the modperl handler if the condition is /not/ met.) Thanks
Re: sethandlers question
On Sun 12 Oct 2008, André Warnier wrote: > > > SetHandler jakarta-servlet > SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk > > PerlXXXHandler My::Module->some_method > > ... > > > > ("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]
Re: sethandlers question
Hi Torsten. Once again, I thank you for the time spent researching and answering my question(s). Unfortunately, I am less fluent in C than you (which is why after all I like and use mod_perl), so sometimes referring me to the C code is not as enlightening to me as it undoubtedly is to you. But I am trying to follow, nevertheless. Torsten Foertsch wrote: On Sun 12 Oct 2008, André Warnier wrote: SetHandler jakarta-servlet SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk PerlXXXHandler My::Module->some_method ... ("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/ ? No, at the moment it runs in a PerlAuthenHandler. As explained the other thread (requests and subrequests), I thought it was more elegant and mod_perl-ish, instead of doing a re-direct to a login page if the user needed authentifying, to having the login page returned by a content handler. (One main reason is that it allows me, in that content handler,to "filter" the login page and insert in it, things I have stored previously in $r->pnotes().) For that thus, when the user is not authenticated when the request hits the PerlAuthenHandler, this handler tries to set the content handler (PerlResponseHandler) to the method send_login_form() in the same module. This works fine when the previous content handler is Apache's default, iow for static pages. But it fails miserably when there is already a specific content handler (like mod_jk) for this Location. Please, have a look again at the ap_process_request_internal() function in httpd-2.x.y/server/request.c. I would first have to know where this thing is. I have never so far looked at the Apache source code, so I need some pointers there. Not that if I look, I would necessarily understand much of it, but I can try. Now, why would I, since you provide the nice explanation below ? 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. So, you mean that for every and each request, Apache re-configures itself ? If that is so, it is quite amazing the speed at which it can serve a page.. 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. Well, I am not sure : The handler set in the configuration file for that Location, is originally "jakarta-servlet" (as per the snippet below). It is I, in my PerlAuthenHandler, who is trying to reset this to "modperl", and in mod_perl, to my send_login_page() method. Before I do that, there is no $r->handler nor PerlResponseHandler set. I may be misunderstanding what you say above of course.. After the ap_location_walk comes the PerlHeaderParserHandler. But it is skipped for subrequests. That's fine, we are always in a main request here. A further examination will show you (probably not) 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 thos
Re: sethandlers question
On Mon 13 Oct 2008, André Warnier wrote: > As explained the other thread (requests and subrequests), I thought > it was more elegant and mod_perl-ish, instead of doing a re-direct to > a login page if the user needed authentifying, to having the login > page returned by a content handler. The apache-way to do this has a name: ErrorDocument or in mod_perl $r->custom_response. Configure an ErrorDocument for 403 and return HTTP_FORBIDDEN in your A...Handler. That has the benefit that the 403 status is logged and that the browser (think about search engines) sees it. But the custom response page must be larger than 512 bytes or you'll encounter problems with IE. If you don't care about that you can use $r->internal_redirect. That is a bit less work to do for your server. > > Please, have a look again at the ap_process_request_internal() > > function in httpd-2.x.y/server/request.c. > > I would first have to know where this thing is. I have never so far > looked at the Apache source code, so I need some pointers there. > Not that if I look, I would necessarily understand much of it, but I > can try. > Now, why would I, since you provide the nice explanation below ? Out of curiosity! Just download the apache source untar it and open in in your favorite editor. C is not that much different from perl and the request.c file is really easy to read. You don't have to modify it, just try to understand what is going on! > So, you mean that for every and each request, Apache re-configures > itself ? If that is so, it is quite amazing the speed at which it > can serve a page.. Just keep in mind for the following that apache is originally designed to have a static configuration. So at start it splits the configuration into blocks, one holds the basic config that is outside all containers and others for each Location/Directory/etc. From those blocks it generates pre-parsed configuration vectors. At runtime each request starts with the basic config fetched from r->server->lookup_defaults then it looks for other vectors matching the request and merges them. But there is another configuration source, .htaccess. Those are read in, compiled and merged in the same function (ap_directory_walk() (hard to understand)) that applies Directory containers (called from ap_run_map_to_storage()). With mod_perl comes yet another configuration source, $r->add_config. This is implemented very similar to .htaccess only the directives are not read from a file but from memory and they are compiled and merged at the time $r->add_config is called. > Well, I am not sure : > The handler set in the configuration file for that Location, is > originally "jakarta-servlet" (as per the snippet below). > It is I, in my PerlAuthenHandler, who is trying to reset this to > "modperl", and in mod_perl, to my send_login_page() method. > Before I do that, there is no $r->handler nor PerlResponseHandler > set. So, why not issue a $r->internal_redirect. I don't exactly know when the SetHandler directive sets $r->handler. Maybe it is done in the type checker phase. So perhaps you have to move your code to Fixup or use $r->add_config(['SetHandler modperl']). > I don't think I can do that, unless I want the PerlTypeHandler or > PerlFixupHandler to become an authentication handler. That would > probably for one upset Adam, for two be kind of funky, no ? Why not? if( $override_handler ) { $r->push_handlers( PerlFixupHandler=>__PACKAGE__.'::fixup' ); $r->pnotes->{override_handler}='modperl'; } ... sub fixup { $_[0]->handler($_[0]->pnotes->{override_handler}; return Apache2::Const::OK; } > Now, in summary : > This is a very specialised authentication module, meant to be used in > very specific circumstances and not for general usage. I control the > environment, so I can pretty much do what I want as long as it does > not crash the system or present some big security hole or the like. > > In my case, that containing the > sethandler jakarta-servlet > is pretty much unique: it is not a sub- or super-location of anything > else, and it fulfills only one very narrow purpose. > To my knowledge, there will be no other module playing a role there, > other than the jakarta-servlet initial handler, plus whatever I > decide to put in there as mod_perl modules and methods. > This for the entire duration of one request. > > Now, assuming I have no other stuff in there than the following lines > > SetHandler jakarta-servlet > SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk > > AuthType MyModule > AuthName MyXyzApp > PerlSetVar MyModule_var1 "value" > PerlAccessHandler My::Module->some_access_method > PerlAuthenHandler My::Module->some_auth_method > PerlAuthzHandler My::Module->some_authz_method > require valid-user > > > > then, if I understand correctly what you write above, since I have no > PerlTransHandler, nor Fixup, etc.. I should be able to do the same > in
Re: sethandlers question
On Tue 14 Oct 2008, André Warnier wrote: > I doubly appreciate not only because my immediate problem is solved, > but also because I learned a lot in the process. Try the $r->add_config again with the right override flag (OR_FILEINFO) and you'll see it will also work. > It seems to me that this whole thread could be collected and > re-arranged into a Tutorial on mod_perl phases, authentication, > interactions with Apache etc.. but honestly at the moment I don't > know where to begin. Find a place where you think it would fit and send in a patch, see http://perl.apache.org/contribute/svn_howto.html#Working_with_SVN on how to get the source. Torsten -- Need professional mod_perl support? Just hire me: [EMAIL PROTECTED]
Re: sethandlers question
Hi. I have read and pondered your earlier responses, and I am sure that the correct solution is somewhere around the ErrorDocument or the $r->internal_redirect. But I wanted to exhaust the other possibilities first, for the sake of completeness and also to learn more about this all. So one little bit at a time : reminder of my config : SetHandler jakarta-servlet SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk AuthType MyModule AuthName MyXyzApp PerlSetVar MyModule_var1 "value" PerlAccessHandler My::Module->some_access_method PerlAuthenHandler My::Module->some_auth_method PerlAuthzHandler My::Module->some_authz_method require valid-user And, in summary, what I was trying to do is : if the PerlAuthenHandler finds that the request is not authenticated, then it tries to change the response handler for this request, from the original "jakarta-servlet" handler, to my own response handler, which in fact returns a login page. (I need something "active" to return the login page, because I need to insert some data into the login page prior to returning it). And for that I used this code in the PerlAuthenHandler : # set our own response handler $r->handler('modperl'); $r->set_handlers(PerlResponseHandler => \&_send_login_form); return OK; One of the possibilities envisioned previously was : Or, a thought that just occurred to me, is the solution for me (stopping jakarta-servlet from running and running my PerlresponseHandler instead), as easy as setting the "no-jk" variable (if I can do that within my PerlAuthenHandler, and how) ? I was tempted to suggest that. But I don't know nothing about jakarta. If you want to try use $r->subprocess_env->{'no-jk'}=1; I tried this, because it was the smallest possible change to my module. It works, in the sense that it sets the "no-jk" variable, which consequently has the effect of making the "jakarta-servlet" handler above not process this link. But it is not a solution for me, since what happens is that the jakarta-servlet handler is in fact still executed by Apache as the response handler, but it probably just returns DECLINED. Then Apache seems to handle the response with its own default handler, which results in a "404 not found" error. The other possibility looked at was : > Or, another thought that just occurred : can I comment out the > > "SetHandler jakarta-servlet" originally, set my PerlresponseHandler > > as the default handler in the , and then *if the user is > > authenticated* (the contrary of my current condition), *set* the > > content handler to be jakarta-servlet instead of modperl ? > Torsten said : Of course. But Torsten did not say how, and I don't know how to do that. How can I set the Apache response handler to be "xyz" ? All I have at this point is the name of that handler : "jakarta-servlet". This is not a perl handler, it is mod_jk.so, the Apache/Tomcat AJP connector. (And I do not need code, I just need a pointer in the right direction). This is now purely for curiosity and for future reference, because after your previous explanations, I am convinced that this is not the right solution for the current problem. In the meantime, I'll go have a look at $r->internal_redirect, which is probably the correct solution.
Re: sethandlers question
Torsten Foertsch wrote: [...] The apache-way to do this has a name: ErrorDocument or in mod_perl $r->custom_response. Configure an ErrorDocument for 403 and return HTTP_FORBIDDEN in your A...Handler. That has the benefit that the 403 status is logged and that the browser (think about search engines) sees it. But the custom response page must be larger than 512 bytes or you'll encounter problems with IE. > If you don't care about that you can use $r->internal_redirect. That is a bit less work to do for your server. 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. 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 ? (So in the new request, I can still access the pnotes set by the original request, via $r->prev->pnotes()). 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 ? 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) ? 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 ? Does Apache still return something to the browser for the original request, or is that completely replaced by whatever the new (redirected) request produces ? After the call to $r->internal_redirect(), should the original request still do something ? (like return Apache2::Const::?) ? Thanks 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.
Re: sethandlers question
On Tue 14 Oct 2008, André Warnier wrote: > When I try this, I get an Apache error with the following logfile > message : [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207] > $r->add_config() has failed: SetHandler not allowed here at > /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n That is an apache error. SetHandler needs the FileInfo override flag, see http://httpd.apache.org/docs/2.2/mod/core.html#sethandler. So, the correct command would be: $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO) or simpler $r->add_config(['SetHandler ...'], ~0) (since you know what directive you are adding). Torsten -- Need professional mod_perl support? Just hire me: [EMAIL PROTECTED]
Re: sethandlers question
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. PerlAuthenHandler "sub { \ return Apache2::Const::FORBIDDEN unless ...; }" ErrorDocument 403 /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; }" 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]
Re: sethandlers question
I am trying the 4 receipes one after the other, in order of easiest to more complicated. Torsten Foertsch wrote: 2) replace $r->handler('modperl') in the aaa phase by $r->add_config(['SetHandler modperl']). This way you override the handler set in the configuration structure. In the fixup phase it is then automagically copied to $r->handler. When I try this, I get an Apache error with the following logfile message : [Tue Oct 14 16:19:39 2008] [error] [client 84.158.163.207] $r->add_config() has failed: SetHandler not allowed here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 416.\n 3) leave the $r->handler('modperl') and add a $r->add_config(['SetHandler none']); When I try this, I get an Apache error with the following logfile message : [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207] $r->add_config() has failed: SetHandler not allowed here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n So it seems that something does not like the $r->add_config from within an AAA method, or at least not when trying to change the handler. I'll try the others now.
Re: sethandlers question
André Warnier wrote: I am trying the 4 receipes one after the other, in order of easiest to more complicated. Torsten Foertsch wrote: 2) replace $r->handler('modperl') in the aaa phase by $r->add_config(['SetHandler modperl']). This way you override the handler set in the configuration structure. In the fixup phase it is then automagically copied to $r->handler. When I try this, I get an Apache error with the following logfile message : [Tue Oct 14 16:19:39 2008] [error] [client 84.158.163.207] $r->add_config() has failed: SetHandler not allowed here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 416.\n 3) leave the $r->handler('modperl') and add a $r->add_config(['SetHandler none']); When I try this, I get an Apache error with the following logfile message : [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207] $r->add_config() has failed: SetHandler not allowed here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n So it seems that something does not like the $r->add_config from within an AAA method, or at least not when trying to change the handler. But > 4) set $r->handler in a fixup handler. this works : $r->set_handlers(PerlAuthzHandler => []); # disable authorization $r->set_handlers(PerlResponseHandler => \&_send_login_form); $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')}); Many, many thanks for all the explanations and tips. I doubly appreciate not only because my immediate problem is solved, but also because I learned a lot in the process. It seems to me that this whole thread could be collected and re-arranged into a Tutorial on mod_perl phases, authentication, interactions with Apache etc.. but honestly at the moment I don't know where to begin.
Re: sethandlers question
On Tue 14 Oct 2008, André Warnier wrote: > reminder of my config : > >> > >> SetHandler jakarta-servlet ... > >> > > And, in summary, what I was trying to do is : > if the PerlAuthenHandler finds that the request is not authenticated, > then it tries to change the response handler for this request, from > the original "jakarta-servlet" handler, to my own response handler, > which in fact returns a login page. > (I need something "active" to return the login page, because I need > to insert some data into the login page prior to returning it). > > And for that I used this code in the PerlAuthenHandler : > > # set our own response handler > $r->handler('modperl'); > $r->set_handlers(PerlResponseHandler => \&_send_login_form); > return OK; The problem is the $r->handler statement. The program flow is this: - ... - uri translation - map to storage - Location container is applied the SetHandler directive is applied to the requests configuration structure. That does not mean $r->handler is set. It is simply noted there is a SetHandler directive active for the request. - aaa - ... - fixup the SetHandler value is copied to $r->handler. See httpd-2.x.y/server/core.c:core_override_type() if (conf->handler && strcmp(conf->handler, "none")) r->handler = conf->handler; That means $r->handler is set only if there was a SetHandler directive and if it was not "SetHandler none". So, that leads us to 4 possible solutions: 1) remove the SetHandler directive from the Location container and set $r->handler either to jakarta-servelet or to modperl in your aaa handler. It won't be touched if other modules don't kick in. mod_dir comes to mind but it reads (fixup handler): /* In case mod_mime wasn't present, and no handler was assigned. */ if (!r->handler) { r->handler = DIR_MAGIC_TYPE; } So, that's not a problem. But there may be other modules that don't check that. 2) replace $r->handler('modperl') in the aaa phase by $r->add_config(['SetHandler modperl']). This way you override the handler set in the configuration structure. In the fixup phase it is then automagically copied to $r->handler. 3) leave the $r->handler('modperl') and add a $r->add_config(['SetHandler none']); 4) set $r->handler in a fixup handler. $r->add_config works very similar to your directives The only difference is the time when it is applied to the config struct. That config is reset after the translation phase. So it is useless to try $r->add_config before. Location containers from the httpd.conf are applied after MapToStorage. So anything you do in your own MapToStorage handler can be overridden in Location containers even if your handler returns OK to skip the core MapToStorage handler. But anything applied after that, that means from the header-parser phase onward overrides the httpd.conf settings. > One of the possibilities envisioned previously was : > >> Or, a thought that just occurred to me, is the solution for me > >> (stopping jakarta-servlet from running and running my > >> PerlresponseHandler instead), as easy as setting the "no-jk" > >> variable (if I can do that within my PerlAuthenHandler, and how) ? > > > > I was tempted to suggest that. But I don't know nothing about > > jakarta. If you want to try use $r->subprocess_env->{'no-jk'}=1; > > I tried this, because it was the smallest possible change to my > module. It works, in the sense that it sets the "no-jk" variable, > which consequently has the effect of making the "jakarta-servlet" > handler above not process this link. > But it is not a solution for me, since what happens is that the > jakarta-servlet handler is in fact still executed by Apache as the > response handler, but it probably just returns DECLINED. That's what I thought it would. Torsten -- Need professional mod_perl support? Just hire me: [EMAIL PROTECTED]
Re: sethandlers question
On Tue 14 Oct 2008, Torsten Foertsch wrote: > On Tue 14 Oct 2008, André Warnier wrote: > > When I try this, I get an Apache error with the following logfile > > message : [Tue Oct 14 16:10:40 2008] [error] [client > > 84.158.163.207] $r->add_config() has failed: SetHandler not allowed > > here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line > > 414.\n > > That is an apache error. SetHandler needs the FileInfo override flag, > see http://httpd.apache.org/docs/2.2/mod/core.html#sethandler. So, > the correct command would be: > > $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO) > > or simpler > > $r->add_config(['SetHandler ...'], ~0) > > (since you know what directive you are adding). Maybe others are interested too, here are 2 private messages: On Wed 15 Oct 2008, André Warnier wrote: > Ok, I did, and it seems to work too : > > So I have 2 sequences that work : > a) > $r->add_config(['SetHandler modperl'], ~0); > $r->set_handlers(PerlAuthzHandler => []); # disable authorization > $r->set_handlers(PerlResponseHandler => \&_send_login_form); > #$r->set_handlers(PerlFixupHandler => sub { > $_[0]->handler('modperl') } ); > > b) > #$r->add_config(['SetHandler modperl'], ~0); > $r->set_handlers(PerlAuthzHandler => []); # disable authorization > $r->set_handlers(PerlResponseHandler => \&_send_login_form); > $r->set_handlers(PerlFixupHandler => sub { > $_[0]->handler('modperl') } ); > > Now, can you explain ? > I don't even understand what "~0" means.. On Wed 15 Oct 2008, Torsten Foertsch wrote: > On Wed 15 Oct 2008, André Warnier wrote: > > 1) you mentioned that it was due to a Apache bug. > > Did I really say bug? I meant an Apache error message. You'll see the > same message if you try something like that: > > > AllowOverride AuthConfig > > > and then have an .htaccess with a SetHandler directive in it. > SetHandler needs "AllowOverride FileInfo". But only AuthConfig is > set. > > The 2nd parameter to add_config is a AllowOverride bit field. It > limits what kind of directives are allowed to be added. Think of it > as if you have read the directives from an untrusted source (like > .htaccess). > > > 2) I do not have a clue why the above would work around that bug. > > Apache wants here not only to be told to add the SetHandler but also > to be ensured "Yes, that is what I want. Just do it!". > > ~0 means all bits turned on. Torsten -- Need professional mod_perl support? Just hire me: [EMAIL PROTECTED]
SetHandlers question, Phase II
Help ! (please) To make a long story short, I created an Apache/mod_perl module for AAA, which after major help from Torsten Foertsch now works fine... on one system, but not on another relatively similar one. The module is called AUTH::StarLogCookie. the critical line is line 419 of the module, which says : $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')}); On one system, this works fine, but on the other one it brings this error in the Apache log : [Tue Oct 14 18:50:26 2008] [error] [client 84.158.163.207] Can't locate object method "handler" via package "AUTH::StarLogCookie" at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 419.\n The system where it works fine is this one : ok-system (Intel-based) : [Tue Oct 14 16:58:47 2008] [notice] Apache/2.2.3 (Debian) DAV/2 SVN/1.4.2 mod_jk/1.2.18 PHP/4.4.4-8+etch4 mod_ssl/2.2.3 OpenSSL/0.9.8c mod_perl/2.0.2 Perl/v5.8.8 configured -- resuming normal operations and the one where it brings the error is this one : bad-system (Apple PPC-based) : [Tue Oct 14 18:59:43 2008] [notice] Apache/2.2.9 (Debian) DAV/2 mod_jk/1.2.26 mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal operations There is a difference between the versions of Apache, perl and mod_perl, so my question is : can this problem be attributed to these version differences ? The funny thing is, the way I understand that code above is to mean : "take a reference to the piece of code between the curly brackets, and pass that code reference as the 2d argument to $r->set_handlers()". But the error message seems to indicate that perl is actually trying to execute "$_[0]->handler()" at that point, no ? Thanks.
Re: SetHandlers question, Phase II
> $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')}); > The funny thing is, the way I understand that code above is to mean : > "take a reference to the piece of code between the curly brackets, and > pass that code reference as the 2d argument to $r->set_handlers()". > But the error message seems to indicate that perl is actually trying to > execute "$_[0]->handler()" at that point, no ? > Actually, this code takes a reference to the value returned when you run the code between the curlies. What I can't figure out is why it works at all in one of your systems :) I think you're wanting: $r->set_handlers(PerlFixupHandler => sub {$_[0]->handler('modperl')}); hth Clint
Re: SetHandlers question, Phase II
Thanks. Duh. Clinton Gormley wrote: $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')}); The funny thing is, the way I understand that code above is to mean : "take a reference to the piece of code between the curly brackets, and pass that code reference as the 2d argument to $r->set_handlers()". But the error message seems to indicate that perl is actually trying to execute "$_[0]->handler()" at that point, no ? Actually, this code takes a reference to the value returned when you run the code between the curlies. What I can't figure out is why it works at all in one of your systems :) I think you're wanting: $r->set_handlers(PerlFixupHandler => sub {$_[0]->handler('modperl')}); Yes. That works. Thank you, my mistake. Shows how easily I get confused when trying to do anything even remotely sophisticated with perl references. Now that you pointed this out, I also don't understand why it is running on the other system. It would be interesting to figure out what the returned value of that call is (was) (probably the old value of handler()), and why it is then different between these two systems also. The module is exactly the same in both cases, and it is called in the same circumstances, from a section configured in the same way. Yes, I know, there must be a difference. Hmm.
Re: SetHandlers question, Phase II
On Wed 15 Oct 2008, André Warnier wrote: > > I think you're wanting: > > > > $r->set_handlers(PerlFixupHandler => sub > > {$_[0]->handler('modperl')}); > > Yes. That works. Better to return something sane from the handler: sub {$_[0]->handler('modperl');0} # 0==Apache2::Const::OK Also consider push_handlers instead of set_handlers. In case other modules already have set a fixup handler. Torsten -- Need professional mod_perl support? Just hire me: [EMAIL PROTECTED]