[mod_python] Apache directory listing

Graham Dumpleton graham.dumpleton at gmail.com
Wed May 30 00:18:35 EDT 2007


Experiment 1.

Using Apache configuration of:

Alias / /Users/grahamd/mod_python/handlers/

<Directory /Users/grahamd/mod_python/handlers>
Order deny,allow
Allow from all
PythonFixupHandler ~/_handler.py
PythonDebug On
Options +Indexes
</Directory>

Note that I am NOT setting SetHandler as only needed for PythonHandler.

Then have _handler.py file in that directory containing:

from mod_python import apache

def fixuphandler(req):
  apache.log_error('fixuphandler %s' % req.uri)
  return apache.OK

when I access the directory, and it runs autoindex, the log file contains:

[Wed May 30 13:45:38 2007] [error] fixuphandler /
[Wed May 30 13:45:38 2007] [error] fixuphandler /index.html
[Wed May 30 13:45:39 2007] [error] fixuphandler /_handler.py
[Wed May 30 13:45:39 2007] [error] fixuphandler /hello.txt

The web browser contains:

Index of /

    * _handler.py
    * hello.txt

This shows what I mean about how it runs handlers through to
fixuphandler() in a subrequest on each item in the directory. The
reason it does this is to determine if it has access rights to items
it might list. It has asked for /index.html because of DirectoryIndex
being set to that in global Apache scope.

I now change my fixuphandler to:

def fixuphandler(req):
  apache.log_error('fixuphandler %s' % req.uri)
  if req.uri == '/_handler.py':
    return apache.HTTP_FORBIDDEN
  return apache.OK

The extra check is making _handler.py forbidden. As a result, web page
now only shows:

Index of /

    * hello.txt

One can tell that one is in this sort of subrequest because req.main
will be set. One could also query the req.main.handler value. For
example:

def fixuphandler(req):
  apache.log_error('fixuphandler %s' % req.uri)
  if req.main and req.main.handler == 'httpd/unix-directory':
    apache.log_error('in autoindex sub request')
  if req.uri == '/_handler.py':
    return apache.HTTP_FORBIDDEN
  return apache.OK

In the log file I then get:

[Wed May 30 13:56:43 2007] [error] fixuphandler /
[Wed May 30 13:56:43 2007] [error] fixuphandler /index.html
[Wed May 30 13:56:43 2007] [error] in autoindex sub request
[Wed May 30 13:56:43 2007] [error] fixuphandler /_handler.py
[Wed May 30 13:56:43 2007] [error] in autoindex sub request
[Wed May 30 13:56:43 2007] [error] fixuphandler /hello.txt
[Wed May 30 13:56:43 2007] [error] in autoindex sub request

You may want to know it is a sub request to autoindex so as to avoid
sending back your own custom content for the forbidden response. If
you are using ErrorDocument, you wouldn't be sending back your own
content though and so it wouldn't have potential for mucking up a
autoindex generated directory listing.

To have custom error details for a error page produced by
ErrorDocument, set error-notes in req.notes:

def fixuphandler(req):
  apache.log_error('fixuphandler %s' % req.uri)
  if req.main and req.main.handler == 'httpd/unix-directory':
    apache.log_error('in autoindex sub request')
  if req.uri == '/_handler.py':
    req.notes['error-notes'] = 'Sorry, you can't access %s' % req.uri
    return apache.HTTP_FORBIDDEN
  return apache.OK

That value will then come through in variable in req.subprocess_env of
ErrorDocument handler.

Experiment 2

Now change Apache configuration to:

Alias / /Users/grahamd/mod_python/handlers/

<Directory /Users/grahamd/mod_python/handlers>
Order deny,allow
Allow from all
SetHandler mod_python
PythonFixupHandler ~/_handler.py
PythonHandler ~/_handler.py
PythonDebug On
Options +Indexes
</Directory>

Thus, am now using SetHandler.

Also change _handler.py to add:

def handler(req):
  req.content_type = 'text/plain'
  print >> req, req.uri
  print >> req, req.filename
  print >> req, req.path_info
  print >> req, req.args
  return apache.OK

If now access the directory, get in the web browser:

/
/Users/grahamd/mod_python/handlers/

None

Thus, the SetHandler is overriding the directory indexing.

To allow directory indexing to work, but all requests to resources
within directory, change configuration to:

Alias / /Users/grahamd/mod_python/handlers/

<Directory /Users/grahamd/mod_python/handlers>
Order deny,allow
Allow from all
<Files ~ .+>
SetHandler mod_python
</Files>
PythonFixupHandler ~/_handler.py
PythonHandler ~/_handler.py
PythonDebug On
Options +Indexes
</Directory>

Now get a autoindex listing from root directory access, but otherwise
handler is called.

If you have subdirectories though and you wanted directory indexes for
those, this will not work. Thus, put back configuration to:

Alias / /Users/grahamd/mod_python/handlers/

<Directory /Users/grahamd/mod_python/handlers>
Order deny,allow
Allow from all
SetHandler mod_python
PythonFixupHandler ~/_handler.py
PythonHandler ~/_handler.py
PythonDebug On
Options +Indexes
</Directory>

Also now change fixuphandler() to be:

def fixuphandler(req):
  apache.log_error('fixuphandler %s' % req.uri)
  if req.finfo.filetype == apache.APR_DIR:
    req.handler = 'httpd/unix-directory'
  return apache.OK

You can now browse through subdirectories okay using autoindex
generated directory listing.

Anyway, experiment with this slowly adding your extra stuff to it. If
you have problems or don't understand something, post the complete
code file so can see what is happening.

Graham


More information about the Mod_python mailing list