On 08/09/2006, at 3:42 PM, Graham Dumpleton wrote:
In regards to:
path,module_name = os.path.split(req.filename)
# Trimming the front part of req.uri
if module_name=='':
req_url = ''
else:
req_url = req.uri[req.uri.index(module_name):]
It is bringing a question I have had for a long time in
mod_python. Is there a way to identify accurately the relative
virtual path of a request other than comparing to the physical
path, especially when using apache definition such as VirtualHost
& Location? For example let's say you define something like:
<Location /myapp/admin/>
AddHandler mod_python .py .html
PythonHandler mod_python.publisher
</Location>
And there comes a request such as http://myserver/myapp/admin/
login.html
How do you determine accurately that the part of the path /myapp/
admin/ is in fact the virtual root of your application ?
If a Directory directive is used, or the handler directives appear
in a .htaccess file,
the you can use req.hlist.directory.
Caveats to this are that prior to mod_python 3.3, if the handler
directive appears
inside of a Files/FileMatch directive within those two contexts,
the value was wrong
and could not be used. Further, prior to mod_python 3.3, the result
would be wrong
if use wildcards in the Directory directive, or the DirectoryMatch
variant was used.
When the Location directive is used, there is no physical directory
which corresponds
to it and so req.hlist.directory wouldn't be valid as its purpose
is to denote the physical
directory a directive was associated with. A caveat to this though,
is that prior to
mod_python 3.3, req.hlist.directory would actually list the path
specified in the
Location directive. This isn't the case though in mod_python 3.3
and it will instead
be None when used in the Location or LocationMatch directives as it
causes problems
otherwise with a non existent path being used as a location to
search for Python
modules.
With my brain being clouded at the moment, I cant remember off the
top of my head
what the correct way is and I would have to check things, but when
you use the
Location directive, isn't req.path_info the part of the URL which
lies below where the
Location directive was specified for. If my memory is correct, this
doesn't mean you
can simply take the length of req.path_info and drop off that much
off req.uri though.
The problem is that req.uri isn't normalised in the way that
req.path_info is, so it may
contain repeating slashes and other crud that can stuff things up.
You need to address
Now I am well and truly confused and not sure if I have broken
mod_python 3.3
or not. Short of it is, that I cannot get something like:
<Location /location>
AddHandler mod_python .xxx
PythonHandler /Users/grahamd/Projects/testing/xxx.py
</Location>
to work. If I use SetHandler instead of AddHandler inside of the
Location directive,
ie.:
<Location /location>
SetHandler mod_python
PythonHandler /Users/grahamd/Projects/testing/xxx.py
</Location>
then it works as I expected, with handler containing:
from mod_python import apache
def handler(req):
req.content_type = 'text/plain'
req.write('req.filename = %s\n' % req.filename)
req.write('req.uri = %s\n' % req.uri)
req.write('req.path_info = %s\n' % req.path_info)
return apache.OK
producing:
req.filename = /usr/local/apache-2.2/htdocs/location
req.uri = /location/cat/dog.xxx
req.path_info = /cat/dog.xxx
Because Location directive is used, then req.filename is sort of
meaningless, although
one could do:
req.write('req.document_root() = %s\n' % req.document_root())
req.write('location = %s\n' % req.filename[len
(req.document_root()):])
and get:
req.document_root() = /usr/local/apache-2.2/htdocs
location = /location
Now the question is whether AddHandler should work within a Location
directive. Since
it doesn't, my first guess is that it can't because no matching
against actual files is being
performed and so no extension for a target could be derived.
I note that using an extension qualifier to the PythonHandler
directive doesn't work
either. Ie., following doesn't call the handler if request is /
dog.xxx or /dog/cat.xxx.
<Location /location>
SetHandler mod_python
PythonHandler /Users/grahamd/Projects/testing/xxx.py | .xxx
</Location>
All probably quite logical and the only way to do something different
based on extension
in the URL would be to specify a fixup handler and not a response
handler, and for
the fixup handler to know it is being used in a location directive,
map the URL itself
somehow and then set req.handler to 'mod_python' and call
req.add_handler() to give
the handler to be called.
Ie., Apache configuration of:
<Location /location>
PythonFixupHandler /Users/grahamd/Projects/testing/xxx.py
</Location>
and handler file containing:
from mod_python import apache
import posixpath
def handler(req):
req.content_type = 'text/plain'
req.write('req.filename = %s\n' % req.filename)
req.write('req.uri = %s\n' % req.uri)
req.write('req.path_info = %s\n' % req.path_info)
req.write('req.document_root() = %s\n' % req.document_root())
req.write('location = %s\n' % req.filename[len
(req.document_root()):])
return apache.OK
# This doesn't copy with concept of path info after extension.
def fixuphandler(req):
extension = posixpath.splitext(req.path_info)[1]
if extension == '.xxx':
req.handler = 'mod_python'
req.add_handler('PythonHandler', handler)
return apache.OK
return apache.DECLINED
BTW, using an absolute path for a handler is new in mod_python 3.3.
Assigning to
req.handler also only works from 3.3 onwards, so don't expect this to
work on older
versions of mod_python.
Having said all that, when you said:
<Location /myapp/admin/>
AddHandler mod_python .py .html
PythonHandler mod_python.publisher
</Location>
is that what you are using and I should actually expect AddHandler to
work inside
of a Location directive?
Graham