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

Reply via email to