Python References
=================
Many places in the configuration take optional ``pyref`` attributes.
These reference a module/function name.
The general pattern is:
``pyref="location:function_name"``
The ``location`` can be a module name, or
``file:/path/to/filename.py``. If it is a literal filename, then
the file is exec'd and turned into a module that way. All
references are to functions (or callable objects), and so you must
give the function name. Note that the ``file:`` case isn't a URL,
just a path.
``pyarg-foo="bar"``
You can pass extra ad hoc arguments to the function using
attributes in this form. This would add the keyword argument
``foo="bar"`` to the function call. All arguments have string
(well, unicode) values.
In addition to the ad-hoc arguments, parameters such as the request
and response, and a logger, will be passed into your ``pyref``
functions. The particular parameters passed in vary for each case, as
do the expected return values. See below for details.
When they are available, ``request`` and ``response`` are `WebOb
`_ objects and ``log`` is a Python
logging object.
Details
-------
Theme
~~~~~
A ```` replaces a ```` and so your pyref
function should return a string href.
You can use a ```` like:
.. code-block:: xml
Then define a function like:
.. code-block:: python
def get_theme(request, response, log):
return "/%s/theme.html" % request.host
``request`` is the original request received by Deliverance.
``response`` is the *content* HTTP response, i.e. the current page to
be themed. Note that this allows you to point to different theme
locations based on conditions of the current page, by inspecting
``response``'s status code, headers or even body.
You can raise :exc:`~deliverance.exceptions.AbortTheme` in this
function (or anywhere else) to signal that the response should be
returned without any theme applied.
Dest
~~~~
Within a ```` tag, you can use a ```` to
dynamically generate the proxy destination from code. Your pyref
function should return a URL. For example:
.. code-block:: xml
with the function:
.. code-block:: python
def get_proxy_dest(request, log):
if not request.remote_addr.startswith('192'):
raise AbortProxy('Bad remote_addr: %r' % request.remote_addr)
return 'http://localhost:10002'
You can return any URL. URI template substitution is *not* performed.
If you raise :exc:`~deliverance.exceptions.AbortProxy` then the
```` will be skipped, and another proxy will be looked for.
(If nothing matches a 404 error is returned.)
Request
~~~~~~~
Within a ```` tag, you can use a ```` to
arbitrarily modify or replace the request object before the proxying
occurs.
Your pyref function must return a webob.Request object. For example:
.. code-block:: xml
with the code:
.. code-block:: python
def modify_proxy_request(request, log):
request.header['X-Project-Name'] = request.host.split('.')[0]
return request
Note that you can modify the request in-place or return a new request.
Response
~~~~~~~~
Within a ```` tag you can use a ```` to
arbitrarily modify or replace the response object returned by the
proxy, before theming occurs.
Your pyref function will receive six arguments (and any custom keyword
arguments you define) -- the signature is (request, response,
orig_base, proxied_base, proxied_url, log):
* orig_base: the original URL base received by Deliverance, e.g. http://localhost:8080/trac
* proxied_base: where dest sent it to, e.g. http://localhost:10001/
* proxied_url: the full destination, e.g. http://localhost:10001/report/1
Since ``request`` is a webob.Request object, you can get the full
original URL from ``request.url``, and all headers.
Your pyref function must return a webob.Response object. For example:
.. code-block:: xml
with the code:
.. code-block:: python
def modify_proxy_response(request, response,
orig_base, proxied_base, proxied_url, log):
response.body += 'look at me!'
return response
Note that you can modify the response in place or return a new webob.Response.
Match, rule, proxy
~~~~~~~~~~~~~~~~~~
The ````, ```` and ```` elements all support a
``pyref`` attribute to determine whether they should be active for the
current request.
Your ``pyref`` function should return a boolean.
The signature is (request, response, response_headers, log):
* response: the current response object, if applicable.
* response_headers: a list of all the headers in the response,
if applicable, including ```` headers.
In ```` elements, ``response`` and ``response_headers`` will be
``None``, because ```` commands occur before any subrequest is
made.
An example:
.. code-block:: python
def match_request(request, response, response_headers, log):
if response.headers.get('x-notheme'):
raise AbortTheme
return True
Disabling
---------
You can disallow Python references using ``deliverance-proxy`` with:
.. code-block:: xml
false