Graham Dumpleton
grahamd at dscpl.com.au
Sun Apr 10 03:18:00 EDT 2005
On 10/04/2005, at 12:57 PM, jarrod roberson wrote: > I need to make sure multiple mod_python handlers are called in a > specific order. > I also need to make sure they are before and/or after other "built in" > handlers such as mod_dav. > > I am using Apache2 and mod_python 3.1.4, I can't find any examples or > specific details on this, and as I am not an Apache2 expert ( yet ) > reading thru the apache docs is not going very fast. In terms of specific order of processing, for any type of handler, the documentation says: All request handler directives have the following syntax: Python*Handler handler [handler ...] [ | .ext [.ext ...] ] Where handler is a callable object that accepts a single argument - request object, and .ext is a file extension. Multiple handlers can be specified on a single line, in which case they will be called sequentially, from left to right. Same handler directives can be specified multiple times as well, with the same result - all handlers listed will be executed sequentially, from first to last. If any handler in the sequence returns a value other than apache.OK, then execution of all subsequent handlers is aborted. For each request, there are also different phases of processing. Taken from the documentation index, these are: ▪ 5.1.2 PythonPostReadRequestHandler ▪ 5.1.3 PythonTransHandler ▪ 5.1.4 PythonHeaderParserHandler ▪ 5.1.5 PythonInitHandler ▪ 5.1.6 PythonAccessHandler ▪ 5.1.7 PythonAuthenHandler ▪ 5.1.8 PythonAuthzHandler ▪ 5.1.9 PythonTypeHandler ▪ 5.1.10 PythonFixupHandler ▪ 5.1.11 PythonHandler ▪ 5.1.12 PythonLogHandler ▪ 5.1.13 PythonCleanupHandler They are in general supposed to be executed in that order if they are defined. Noting though that authenhandler and authzhandler are only executed if there is also appropriate configuration information in the Apache configuration file which triggers their use. Some of the earlier phases are also only triggered in certain situations. Now take as example a .htaccess file which contains: SetHandler mod_python PythonHeaderParserHandler mptest::headerparser PythonAccessHandler mptest::accesshandler PythonHandler mptest::handler PythonLogHandler mptest::loghandler PythonCleanupHandler mptest::cleanuphandler and "mptest.py" contains: from mod_python import apache import time class _Handler: def __init__(self,phase,status=apache.OK,delay=0): self.__phase = phase self.__status = status self.__delay = delay def __call__(self,req): req.log_error("</%s>"%self.__phase) time.sleep(self.__delay) req.log_error("<%s>"%self.__phase) return self.__status postreadrequesthandler = _Handler("postreadrequesthandler") transhandler = _Handler("transhandler") headerparserhandler = _Handler("headerparserhandler") inithandler = _Handler("inithandler") accesshandler = _Handler("accesshandler") authenhandler = _Handler("authenhandler") authzhandler = _Handler("authzhandler") typehandler = _Handler("typehandler") fixuphandler = _Handler("fixuphandler") handler = _Handler("handler",status=apache.DECLINED) loghandler = _Handler("loghandler") cleanuphandler = _Handler("cleanup") If I request a plain text file residing in that directory in the log file I will see: [Sun Apr 10 02:56:46 2005] [notice] mod_python: (Re)importing module 'mptest' [Sun Apr 10 02:56:46 2005] [error] [client 128.121.126.33] </accesshandler> [Sun Apr 10 02:56:46 2005] [error] [client 128.121.126.33] <accesshandler> [Sun Apr 10 02:56:46 2005] [error] [client 128.121.126.33] </handler> [Sun Apr 10 02:56:46 2005] [error] [client 128.121.126.33] <handler> [Sun Apr 10 02:56:46 2005] [error] [client 128.121.126.33] </loghandler> [Sun Apr 10 02:56:46 2005] [error] [client 128.121.126.33] <loghandler> [Sun Apr 10 02:56:47 2005] [error] [client 128.121.126.33] </cleanup> [Sun Apr 10 02:56:47 2005] [error] [client 128.121.126.33] <cleanup> Note that because apache.DECLINED was returned from handler(), Apache will fall back to using the "default-handler" and will serve up the raw contents of the file. Unfortunately, if the file requested was a ".php" file, the raw contents of the file will be returned and not the processed output from running the PHP module on the raw file. What to do to still have the ".php" file processed but the other handler phases still be executed by mod_python isn't obvious though. What you need to know is that the "SetHandler" and "AddHandler" directives only apply to the "PythonHandler" directive and not to all the others. Thus, if the following .htaccess file is instead used: #SetHandler mod_python PythonHeaderParserHandler mptest::headerparser PythonAccessHandler mptest::accesshandler PythonHandler mptest::handler PythonLogHandler mptest::loghandler PythonCleanupHandler mptest::cleanuphandler Ie., comment out the "SetHandler", then "PythonHandler" directive doesn't get applied. Make a request against a ".php" file in the directory and one sees in the log file: [Sun Apr 10 03:01:18 2005] [notice] mod_python: (Re)importing module 'mptest' [Sun Apr 10 03:01:18 2005] [error] [client 128.121.126.33] </accesshandler> [Sun Apr 10 03:01:18 2005] [error] [client 128.121.126.33] <accesshandler> [Sun Apr 10 03:01:18 2005] [error] [client 128.121.126.33] </loghandler> [Sun Apr 10 03:01:18 2005] [error] [client 128.121.126.33] <loghandler> [Sun Apr 10 03:01:18 2005] [error] [client 128.121.126.33] </cleanup> [Sun Apr 10 03:01:18 2005] [error] [client 128.121.126.33] <cleanup> Note that "handler()" isn't called, the others still are and I get my rendered PHP output displayed in the browser. Thus you can see that a non mod_python content handler can be mixed with other handlers which do use mod_python. If you were to add time delays in the various phases to slow things done, you would see that the "PHP" output will appear on your browser at the point where "handler()" would otherwise be called. This therefore indicates that the log handler and later phases only get executed after the PHP module has been executed to return the page content. In terms of mod_dav, as far as I can see, if you don't set AddHandler or SetHandler directives, you should be able to define an access handler or log handler etc and mod_dav will be called where the handler would otherwise. One final thing to try with the above is set the .htaccess file to contain only: PythonHandlerModule mptest When I know request the ".php" file I see: [Sun Apr 10 03:08:47 2005] [notice] mod_python: (Re)importing module 'mptest' [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] </headerparserhandler> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] <headerparserhandler> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] </accesshandler> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] <accesshandler> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] </loghandler> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] <loghandler> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] </cleanup> [Sun Apr 10 03:08:47 2005] [error] [client 128.121.126.33] <cleanup> I don't quite understand why the header parser handler is executed when the "PythonHandlerModule" directive is used, but not when "PythonHeaderParserHandler" is used explicitly. BTW, "PythonHandlerModule" is actually broken. It works here because a handler for every phase is defined. According to the documentation it is meant to ignore the fact that a handler for a phase isn't there and simply just call those which are. It doesn't do this though and raises a 500 error. Problem is logged as: http://issues.apache.org/jira/browse/MODPYTHON-46 I inadvertently fixed this in an older version of Vampire in an alternate way I provided of defining non content handlers, but then I broke it again in one of the more recent versions. Have fixed it again for next version. :-) Anyway, the only thing I didn't explain here was when you have: PythonHandler a b c or: PythonHandler a PythonHandler b PythonHandler c I think the documentation I quote about this at the start was reasonably clear on that one though. Hope this explains things. If it doesn't, you should perhaps explain the specific problem you are having. Graham
|