125 lines
4.4 KiB
Python
125 lines
4.4 KiB
Python
import logging
|
|
import re
|
|
|
|
from urlparse import urlparse
|
|
|
|
from mandaye.filters.default import MandayeFilter
|
|
from mandaye.response import _500
|
|
|
|
# TODO: add an external url mapping
|
|
|
|
class Dispatcher(object):
|
|
""" The dispatcher is the main class of Mandaye
|
|
It allows you to launch the right filter on the reqest and the response
|
|
"""
|
|
|
|
def __init__(self, env, target_url, mapping=dict()):
|
|
""" target_url: the full url of your destination
|
|
"""
|
|
self.target = urlparse(target_url)
|
|
self.env = env
|
|
self.env['target'] = self.target
|
|
self.mapping = mapping
|
|
self.filter = MandayeFilter(self.env, self.target)
|
|
self.req_mapping = self._parse_mapping(self.mapping)
|
|
|
|
def _parse_mapping(self, mapping):
|
|
""" parse the mapping on every request
|
|
"""
|
|
req_mapping = {
|
|
'on_request': [],
|
|
'on_response': [],
|
|
'response': None,
|
|
'target': None
|
|
}
|
|
|
|
for conf in mapping:
|
|
if conf.has_key('path') and \
|
|
re.match(conf['path'], self.env['PATH_INFO']):
|
|
if not conf.has_key('method') \
|
|
or conf['method'] == self.env['REQUEST_METHOD']:
|
|
for hookname in req_mapping:
|
|
if conf.has_key(hookname):
|
|
if isinstance(req_mapping[hookname], list):
|
|
req_mapping[hookname].extend(conf[hookname])
|
|
else:
|
|
req_mapping[hookname] = conf[hookname]
|
|
return req_mapping
|
|
|
|
def _call_hook(self, hook, *args):
|
|
if hook and hook.has_key('filter'):
|
|
values = hook.get('values')
|
|
if not values:
|
|
values = dict()
|
|
if hook.has_key('condition'):
|
|
return hook['filter'](self.env, values, hook['condition'], *args)
|
|
else:
|
|
return hook['filter'](self.env, values, *args)
|
|
else:
|
|
logging.warning("%s hook failed (no filter option)" % self.env['PATH_INFO'])
|
|
return None
|
|
|
|
def get_target_url(self):
|
|
""" Return the destination url
|
|
"""
|
|
# Disable reverse proxy if we have a static response
|
|
if self.req_mapping['response']:
|
|
return None
|
|
if self.req_mapping['target']:
|
|
url = self.req_mapping['target']
|
|
else:
|
|
url = self.target.geturl() + self.env['PATH_INFO']
|
|
if self.env['QUERY_STRING']:
|
|
return url + "?" + self.env['QUERY_STRING']
|
|
else:
|
|
return url
|
|
|
|
def get_response(self, request):
|
|
""" Called if you have a response hook for this request
|
|
"""
|
|
response = self._call_hook(self.req_mapping['response'],
|
|
request)
|
|
if not response:
|
|
return _500(self.env["PATH_INFO"], "The response hook failed")
|
|
# loading defaults filters
|
|
response = self.filter.on_response(response)
|
|
return response
|
|
|
|
def mod_request(self, request):
|
|
""" Modify the request
|
|
request: MandayeRequest object with cookies and headers
|
|
Return the request object """
|
|
# Loading defaults filters
|
|
request = self.filter.on_request(request)
|
|
|
|
# Calling hook function
|
|
for hook in self.req_mapping['on_request']:
|
|
new_request = self._call_hook(hook, request)
|
|
if new_request:
|
|
request = new_request
|
|
else:
|
|
logging.warning("%s On_request hook %s failed" % (self.env['PATH_INFO'],
|
|
self.req_mapping['on_request']['filter']))
|
|
return request
|
|
|
|
def mod_response(self, request, response):
|
|
""" Modify the response
|
|
request: the Mandaye request
|
|
response: MandayeResponse object with cookies, headers and HTML
|
|
you can modify the cookies and the HTTP headers """
|
|
|
|
# loading defaults filters
|
|
response = self.filter.on_response(response)
|
|
|
|
# Calling hook function
|
|
for hook in self.req_mapping['on_response']:
|
|
new_response = self._call_hook(hook, request, response)
|
|
if new_response:
|
|
response = new_response
|
|
else:
|
|
logging.warning("%s On_response hook %s failed" % (self.env['PATH_INFO'],
|
|
self.req_mapping['on_response']['filter']))
|
|
|
|
return response
|
|
|