[mod_python] How to make a handler for static files?

Deron Meranda deron.meranda at gmail.com
Mon Feb 27 11:10:48 EST 2006


Even though Apache mod_rewrite may work better, here's
just a few comments on your mod_python approach.  If nothing
else it might be useful as an example....

On 2/27/06, Scott Chapman <scott_list at mischko.com> wrote:
> > from mod_python import apache
> > import os
> > import psycopg2
> >
> > def parse_uri(uri):
> >     uri_list = uri.split('/')
> >     uri_list.insert(0,'')
> >     uri_list=uri_list[-3:]
> >     return uri_list

Consider using Python's urlparse module instead.

> > def _getInternalName(alias):
> >         _conn = psycopg2.connect("user=foo dbname=bar host=127.0.0.1 password=barfoo")
> >         _cursor = _conn.cursor()
> >         query = "SELECT hostname FROM host_aliases WHERE external_name = %s"
> >         parms = [alias]

Should probably use alias.tolower()  (or toupper()).  Hostnames are
generally case-insensitive (in ASCII).

> >         _cursor.execute(query, parms)
> >         rval = _cursor.fetchone()
> >         if rval:
> >             rval = rval[0]
> >         _conn.rollback()

Why a rollback?  A commit() is probably better.

> >         _conn.close()
> >         return (rval)
> >
> > def handler(req):
> >     def _log(message):
> >         req.log_error(message)
> >
> >     debug = True
> >
> >     (subsite, moduleName, methodName)= parse_uri(req.uri)
> >     internalName = _getInternalName(req.hostname)
> >     if subsite:
> >         internalName = _getInternalName(subsite)
> >
> >     if not internalName:
> >         if debug: _log('static_handler - illegal host name')
> >         raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
> >
> >     orig_path = req.filename
> >
> >     (path, filename) = os.path.split(req.filename)
> >     new_path = os.path.normpath(path + '/' + internalName + '/' + filename)

Use os.path.join() instead of a+'/'+b+'/'+c.

> >     if os.path.exists(new_path):
> >         use_path = new_path
> >     elif os.path.exists(orig_path):
> >         use_path = orig_path
> >     else:
> >         raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
> >
> >     if debug: _log('static_handler - used path: %s' % use_path)

You should set up some other headers too.  Mimimally something
like this:

    import mimetypes, os, stat, time, sha

    ct, et = mimetypes.guess_type( use_path )
    if not ct:
        ct = 'application/octet-stream'
    req.content_type = ct
    if et:
        req.headers_out['Content-Encoding'] = et

    mtime = os.stat( use_path )[ stat.ST_MTIME ]
    lastmod = time.strftime('%a, %d %m %Y %H:%M:%S GMT',
                           time.gmtime(mtime) )
    req.headers_out['Last-Modified'] = lastmod
    req.headers_out['Accept-Ranges'] = 'none'
    hash = sha.sha()
    sha.update( open(use_path,'rb').read() )
    req.headers_out['ETag'] = hash.hexdigest()

> >     req.sendfile(use_path)
> >     return apache.OK

If you really want to get advanced, try handling byte ranges too.
--
Deron Meranda



More information about the Mod_python mailing list