Package: collective.diazo.readheaders
ContentsIntroductionAbout this packageExampleWSGI pipelineFront-endDeployment optionsCherokee, uWSGI and Pip/BuildoutContributingContributorsChangelogIntroduction“What’s Diazo?”, I hear you say.  Fromdiazo.org:Diazo allows you to apply a theme contained in a static HTML web page to a
dynamic website created using any server-side technology. With Diazo, you
can take an HTML wireframe created by a web designer and turn it into a
theme for your favourite CMS, redesign the user interface of a legacy web
application without even having access to the original source code, or
build a unified user experience across multiple disparate systems, all in a
matter of hours, not weeks.When using Diazo, you will work with syntax and concepts familiar from
working with HTML and CSS. And by allowing you seamlessly integrate XSLT
into your rule files, Diazo makes common cases simple and complex
requirements possible.About this packageThis package extends the standard theming middleware of Diazo to add the
ability to read the location of a rules XML file from the WSGI environment.
This means, amongst being able to read a rules location from the environment
for the local user, that an upstream service (such as a web server, reverse
proxy, caching proxy, etc) is able to control the theme the middleware is using
– and change this for any given request.  This contrasts with the
configuration-based approach taken by Diazo’s standard middleware, which
requires a fixed path to be specified for the middleware.So, this means with the right WSGI configuration, you could conceivably have
one Diazo instance serving any number of themes without needing to explicitly
configure paths, urlmaps or the like.  If you combine this with a suitable
front-facing tool (such as a configurable web server like Apache, Nginx,
Cherokee, or any other), then you can have this one Diazo instance theming any
number of applications, and theming differently based upon any condition your
web server supports – such as incoming host name, HTTP vs HTTPS, specific URLs
or regex, headers, IP addresses, and more.  To achieve this, all you need to do
is set the right HTTP header – which is the path to your rules file – and
ensure this is sent to your middleware based upon your various conditions.ExampleIn this example, we can deploy this extended Diazo middleware to act as a
one-size-fits-all theming backend behind our web server. With the right
WSGI pipeline, we can have one WSGI pipeline servicing as many backends
as you like, serving any number of different themes, all without any explicit
WSGI configuration.  Keep in mind the potential of header spoofing - exercise
extreme care.WSGI pipelinePrepare a configuration for PasteScript as follows:[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 5000

[composite:main]
use = egg:Paste#urlmap
/ = default

[pipeline:default]
pipeline = theme
           proxy

[filter:theme]
use = egg:collective.diazo.readheaders
#You can use any other Diazo middleware options here, too!
read_network = True
debug = True

[app:proxy]
use = egg:djb.headerproxyOver the standard Diazo/WSGI configuration seen athttp://docs.diazo.org/en/latest/quickstart.htmlkeen-eyed viewers will notice
the following:We usecollective.diazo.readheadersinstead ofdiazo- this
allows theX-Diazo-Rulesheader to be read from the incoming WSGI
environment and used as the traditionalrulesoption. This means
that any format therulesoption accepts (such as network-based URLs)
will work if set as this header. In the specific case of network URLs, you
will need to configureread_networkto be enabled.This section automatically accepts any and add options that Diazo does: seehttp://docs.diazo.org/en/latest/deployment.html#wsgi- and we demonstrate
this above.We use the special WSGI proxydjb.headerproxywhich will reverse proxy to
an arbitrary location based upon incoming headers. By comparison, the
standard Paste proxy requires an explicitly defined address in the
configuration. As per the documentation fordjb.headerproxy, the headers
upstream are, by default, expected to beX-Proxy-Force-HostandX-Proxy-Force-Scheme– this mapping is configurable, however.Front-endNow, in our front-end server, we can configure our reverse proxy and
set the headers accordingly.  For instance, with Apache you might do the
following:RequestHeader set "X-Diazo-Rules" "/path/to/rules.xml"
RequestHeader set "X-Proxy-Force-Host" "app-server.example.com:8080"
RequestHeader set "X-Proxy-Force-Scheme" "http"
RewriteRule / http://localhost:5000 [L,P]In which, the rewrite rule points to the location of the service running
the above Paste WSGI configuration.Don’t forget that theX-Diazo-Rulesoption will be interpreted on the
local machine running the WSGI pipeline. So, if you refer to a local file
it will be local tothat machine. This point is moot if you are running
Diazo on the same machine - but it should still be emphasised.  Keep in
mind too that you can configure options like this:RequestHeader set X-Diazo-Rules "http://example.com/path/to/rules.xml"and they will work as well (assuming, at least in this case, that your
middleware has theread_networkoption enabled).Deployment optionsYou can deploy using your choice of server – it doesn’t need to be Paste.
Similarly, you can deploy with your choice of front-end – it certainly doesn’t
need to be Apache.  If you’ve deployed something similar to the above, then
consider contributing your deployment configuration here!Cherokee, uWSGI and Pip/BuildoutOne successful deployment utilises theCherokee web serveranduWSGIand runs uWSGI using a local socket on the web server machine. Cherokee (much
like Ngnix) can talk directly to uWSGI, which in turn is able to directly
utilise Paste-style ini configuration, like the one above.  For uWSGI, the only
addition configuration needed was to add this to the top of the ini file:[uwsgi]
home = /opt/diazo
processes = 8
vacuum = true
master = true
socket = %(home)/var/uwsgi.sock
pythonpath = %(home)/eggs/*.egg
pythonpath = %(home)/src/*and then uWSGI, which was simply installed along with all dependencies thus:cd /opt/diazo
virtualenv .
source bin/activate
pip install uwsgi collective.diazo.readheaders djb.headerproxycan be easily started using:./bin/uwsgi --ini-paste diazo.iniwhich reads its own options from the configuration, together with the WSGI
pipeline and associated config.  For bonus points, you can also deploy the
above withBuildouttoo:[buildout]
parts = lxml instance
eggs-directory = eggs

[lxml]
recipe = z3c.recipe.staticlxml
egg = lxml

[instance]
recipe = zc.recipe.egg
eggs =
    collective.diazo.readheaders
    djb.headerproxy
    uwsgi
dependent-scripts = truePhew!ContributingJoin in athttps://github.com/collective/collective.diazo.readheaders–
if you’re already a member of the Collective then you can already push changes.
Otherwise, fork away and send a pull request.ContributorsDavid Beitey, AuthorChangelog0.1 (2012-08-09)Package created using templer
[David Beitey]