|
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
|