Deliverance á la WSGI for Plone
Exciting times to be a Plone developer...
Deliverance is the New Kid on the Block[tm] in the Plone world. I find the whole concept very intriguing and have decided to give it a try on both of my current new projects. (No risk, no fun, eh!?)
One of the two projects is smaller in scope where I am both the Zope/Plone developer and the HTML/CSS handyman and the other a larger affair together with another Zopista and an external web agency with up to five more people, none of which is experienced with - or much interested in - Plone, so I am curious, how Deliverance will hold up in these two quite different scenarios.
Now, if you just want to dip your toes into the proverbial water, I suggest you check out Martin Aspeli's Deliverance recipe (does that man ever sleep?) However, Martin's recipe, along with any other tutorial that I found floating about, uses deliverance in its so-called proxy mode where a second daemon is fired up that mediates between the web- and application server. This is not optimal, of course, as it pretty much defeats the whole point of the WSGI concept, so I set out to create a setup, where Plone would be themed by Deliverance configured as a WSGI middleware. Forthwith my notes:
I conducted my test on Mac OS X 10.5.2 with Python 2.4.5 installed via Macports. I didn't use virtualenv (although I should have) but had to make sure throughout the whole process, that python2.4 was used (as opposed to Leopard's default 2.5.1). To do that, I installed easy_install and setuptools explicitly for 2.4:
wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python2.4 ez_setup.py
sudo python ez_setup.py -U setuptools
Before dealing with Deliverance I set up a WSGI enabled Plone instance. The buildout provided by repoze.plone proved to be the best candidate to do so (believe me!)
svn co http://svn.repoze.org/buildouts/repoze.plone/trunk repoze.plone
cd repoze.plone
python2.4 bootstrap.py
./bin/buildout
I then fired up the new instance as per instructions:
./bin/supervisord
./bin/addzope2user admin admin
I then could add a Plone instance foo at localhost:8080 just as always. I then stopped the zope instance so:
./bin/supervisorctl stop zope
and then restarted it using paster:
./bin/paster serve etc/zope2.ini
and sure enough, localhost:8080/foo was still there!
Now the only thing missing was Deliverance itself. To make it available for the instance, I simply easy_installed it into my system (this is the part, where next time I'll use virtualenv!):
sudo easy_install-2.4 Deliverance
This enabled me to add the following snippet to etc/zope2.ini:
[filter:deliverance]
paste.filter_app_factory = deliverance.wsgimiddleware:make_filter
theme_uri = file:///%(here)s/layout.html
rule_uri = file:///%(here)s/rules.xml
To use the deliverance as a filter in the WSGI stack I just had to add it somewhere. I chose to add it just after zope2 itself, so that my pipeline section looked like so:
[pipeline:main]
pipeline = egg:Paste#cgitb
egg:Paste#httpexceptions
egg:repoze.retry#retry
egg:repoze.tm#tm
egg:repoze.vhm#vhm_xheaders
errorlog
deliverance
zope2
Before restarting zope (or rather 'reserving it with paster') I had to add the rulefiles mentioned in the filter declaration. Eager as I was at this point, I simply borrowed the trivial default rule and theme from Martin's recipe, spiced it up a little with one of repoze.org's own rule files and created a etc/rules.xml file that looked like this:
<?xml version="1.0" encoding="UTF-8"?>
<rules xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns="http://www.plone.org/deliverance">
<prepend theme="//head" content="//head/link" nocontent="ignore" />
<prepend theme="//head" content="//head/style" nocontent="ignore" />
<append theme="//head" content="//head/script" nocontent="ignore" />
<append theme="//head" content="//head/meta" nocontent="ignore" />
<append-or-replace
theme="//head"
content="//head/title"
nocontent="ignore" />
<append-or-replace theme="//div[@id='content']"
content="//div[@id='region-content']"
nocontent="ignore" />
</rules>
and a etc/layout.html file that looked like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
<title>The Theme</title>
</head>
<body>
<h1>A theme</h1>
<div id="content">
</div>
<hr>
<address></address>
<!-- hhmts start -->Last modified: Fri Mar 16 09:33:37 CDT 2007 <!-- hhmts end -->
</body> </html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>layout</title>
</head>
<body>
</body>
</html>
Now I could stop the foreground paster process, fire it up again, hit reload in my browser and voila! Bob was my proverbial Uncle!
Next, I'll give mod_wsgi a try. But, of course, not the one for Apache but... yup, there's a mod_wsgi for nginx, too, yay! Stay tuned...
P.S. I'd like to take this opportunity to thank Chris, Tres and Paul for their efforts to connect Zope and Plone with non-techies and non-Zopistas. I'm very confident that you guys are creating some serious groundwork here that will benefit us immensely during the next eight years! Rock on!

Great post, please keep us informed
Thanks a lot for a great writeup, Tom. Let us know how it all winds up, particularly the nginx.
--Paul