Monday, January 09, 2006

Creating your own mod_python request dispatcher

Creating your own mod_python request dispatcher that maps url's to python request handlers.

Conceptually I have something that looks like this:

+-------------+
| Clients |
| Web Browser |
+-------------+
| [http://somecooldomain.com/coorequest]
| ^
| | [Cool Response]
V |
+--------+ +------------+ +---------------+ +---------+
| Apache | --> | Mod_Python | --> | dispatcher.py | --> | cool.py | --+
| (A) | <-- | | <-- | (B) | | (D) | |
+--------+ +------------+ +---------------+ +---------+ |
| ^ |
| | |
| +------------------------+
V
+-------------+
| urlmap.conf |
| (C) |
+-------------+


A) Apache Configuration:
On my server I have mod_python set up to handle any request that comes in without a file extension. That way I can have those cool REST style URI's. I use the apache "FilesMatch" directive in my httpd.conf file to look for any request that does not contain a '.' before the '?' in the query string:


<FilesMatch "(^[^\.]*$|^[^\?]*[\?]+[^$]+$)">
SetHandler python-program
PythonHandler common.dispatch.dispatcher
PythonDebug On
</FilesMatch>


B) dispatcher.py
The source for dispatcher.py can be found here.

C) Example urlmap.conf


[somecooldomain.com]
/=cooldomain.handlers.home.handler
/signup=cooldomain.handlers.member.signup
/login=cooldomain.handlers.member.login
/logout=cooldomain.handlers.member.logout
/cool=cooldomain.handlers.cool.handler



D) cool.py
This is the handler that generates your content. In my content handlers I usually do things like query the database, process business logic, select a cheetah template and return the result as html.

In summary I use this approch for a couple of reasons, first it allows me to decouple my url's from my python code that way I don't have python code + html sitting around in the same directory. Secondly I get one piece of code that handles every request. (good for sessions and things like that)

6 comments:

Anonymous said...

An interesting way of doing things. However it may be prudent to find some way of caching the config. Reloading a file for every request may become and expensive task...

cludwin said...

Absolutely disk hits are slow. I learned that the hard way with Cheetah, never use "#include" it is a disk hit use inherritance instead.

The urlmap.config file should only be read once on import. mod_python caches for me. This setup perfroms quite well.

Anonymous said...

Your concept of a "URL config" is quite similar to that of Django's URLconfs. Check it out, if you haven't already!

Anonymous said...

Yeah, reminds me of Django's URL config.

Neet hack though. Nice re in httpd.conf.

And thanks for the ascii art.

cludwin said...

thanks for the comments,
who needs uml when you have ascii art ;)

Anonymous said...

Bad link on the blog:

B) dispatcher.py
The source for dispatcher.py can be found here.

Points to the following url:
http://socallocal.com/blog/dispatcher.py

Which does not work.....any chance you could correct? I wouldn't mind having a look at dispatcher.py.

Thanks for the post!!!!