[z3-checkins] r41931 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster
ianb at codespeak.net
ianb at codespeak.net
Fri Apr 6 05:36:03 CEST 2007
Author: ianb
Date: Fri Apr 6 05:36:02 2007
New Revision: 41931
Modified:
z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py
Log:
Refactoring that changes no functionality
Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py
==============================================================================
--- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original)
+++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 05:36:02 2007
@@ -27,6 +27,12 @@
class DeliveranceDispatcher(object):
+ """
+ Main WSGI application that handles dispatching to the API handler,
+ redirects, static files, and finding the proper remote URI to
+ proxy to.
+ """
+
def __init__(self, app_conf):
data_dir = app_conf['data_dir']
init_domain = app_conf.get('init_domain')
@@ -50,6 +56,9 @@
self.clean_environ_headers_regex = None
def __call__(self, environ, start_response):
+ """
+ WSGI interface
+ """
if 'paste.registry' in environ:
environ['paste.registry'].register(current_environ, environ)
self.clean_environ_headers(environ)
@@ -58,7 +67,7 @@
environ['dvhoster.base_url'] = construct_url(
environ, with_query_string=False,
path_info='')
- path_info = norm_path(environ.get('PATH_INFO', ''))
+ environ['PATH_INFO'] = path_info = norm_path(environ.get('PATH_INFO', ''))
if path_info.startswith('/.deliverance'):
path_info_pop(environ)
subapp = DomainInfoApp(domain_info)
@@ -70,68 +79,26 @@
subapp = StaticURLParser(
domain_info.rule_dir)
return subapp(environ, start_response)
-
- static_path = os.path.join(domain_info.static_dir,
- path_info.lstrip('/'))
- static_fn = self.find_file(static_path)
- if static_fn is not None:
- # Explicit override of a file
- app = FileApp(static_fn)
- return app(environ, start_response)
- try:
- remote_uris = domain_info.remote_uris
- except AttributeError:
+
+ static_app = self.find_static_file(domain_info, path_info)
+ if static_app:
+ return static_app(environ, start_response)
+
+ if not domain_info.initialized:
exc = httpexceptions.HTTPNotFound(
"This domain has not yet been configured (no remote "
"URI has been configured for %s)"
% domain_info.domain)
return exc(environ, start_response)
- remote_uri = None
- current_uri = construct_url(environ)
- for redirect_info in domain_info.redirects:
- if 'path' in redirect_info:
- if redirect_info['path'] == path_info:
- new = redirect_info['rewrite']
- new = urlparse.urljoin(current_uri, redirect_info['rewrite'])
- exc = httpexceptions.HTTPMovedPermanently(
- headers=[('Location', new)])
- return exc(environ, start_response)
- elif 'prefix' in redirect_info:
- assert redirect_info['prefix'].endswith('/')
- new_uri = None
- if path_info == redirect_info['prefix'][:-1]:
- new_uri = redirect_info['rewrite'] + '/'
- elif path_info.startswith(redirect_info['prefix']):
- new_uri = redirect_info['rewrite']
- if not new_uri.endswith('/'):
- new_uri += '/'
- new_uri += path_info[len(redirect_info['prefix']):]
- if new_uri is not None:
- new_uri = urlparse.urljoin(current_uri, new_uri)
- exc = httpexceptions.HTTPMovedPermanently(
- headers=[('Location', new_uri)])
- return exc(environ, start_response)
- for header_name, header_value in domain_info.additional_request_headers:
- header_name = 'HTTP_%s' % header_name.upper().replace('-', '_')
- environ[header_name] = header_value
+ redir_app = self.check_redirects(
+ path_info, domain_info, environ)
+ if redir_app:
+ return redir_app(environ, start_response)
- for remote_uri_info in remote_uris:
- path = str(remote_uri_info['path'])
- if not path.endswith('/'):
- path += '/'
- if path_info + '/' == path:
- exc = httpexceptions.HTTPMovedPermanently(
- headers=[('location', construct_url(environ, path_info=path_info+'/'))])
- return exc(environ, start_response)
- if path_info.startswith(path):
- # Found a match
- remote_uri = remote_uri_info.get('remote_uri')
- environ['SCRIPT_NAME'] += path[:-1]
- environ['PATH_INFO'] = path_info[len(path)-1:]
- if self.find_remote_uri:
- remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf)
- break
+ self.set_additional_headers(domain_info, environ)
+
+ remote_uri = self.match_remote_uri(path_info, domain_info, environ)
if not remote_uri:
exc = httpexceptions.HTTPNotFound(
"No URL is mapped to %r (somewhat oddly); only %s prefixes "
@@ -139,6 +106,7 @@
% (path_info, ', '.join([repr(r['path'])
for r in remote_uris])))
return exc(environ, start_response)
+
should_theme_uri = True
if self.should_theme_uri:
should_theme_uri = self.should_theme_uri(
@@ -146,12 +114,15 @@
app = proxyapp.ForcedProxy(
remote=remote_uri,
force_host=True)
+
if self.rewrite_links:
app = relocateresponse.RelocateMiddleware(
app, old_href=remote_uri)
+
rule_uri = construct_url(
environ, with_query_string=False,
path_info='/_rules/rule.xml')
+
if should_theme_uri:
app = DeliveranceMiddleware(
app,
@@ -160,14 +131,25 @@
renderer=Renderer)
return app(environ, start_response)
- def find_file(self, path):
- if os.path.isdir(path):
- path = os.path.join(path, 'index.html')
- if os.path.exists(path):
- return path
+ def find_static_file(self, domain_info, path_info):
+ """
+ If the request matches a static file, returns a WSGI
+ application to handle that file. Else returns None.
+ """
+ static_path = os.path.join(domain_info.static_dir,
+ path_info.lstrip('/'))
+ if os.path.isdir(static_path):
+ static_path = os.path.join(
+ static_path, 'index.html')
+ if os.path.exists(static_path):
+ return FileApp(static_path)
return None
def clean_environ_headers(self, environ):
+ """
+ Remove any request headers that overlap with internal request
+ headers (as configured with ``clean_environ_headers_regex``).
+ """
if not self.clean_environ_headers_regex:
return
for key in environ.keys():
@@ -176,6 +158,12 @@
del environ[key]
def get_domain_info(self, environ):
+ """
+ Get the DomainInfo object associated with the request.
+
+ May raise a redirect if the requested host is not the
+ canonical host.
+ """
domain = environ['HTTP_HOST']
if ':' in domain:
domain = domain.split(':', 1)[0]
@@ -200,3 +188,75 @@
raise exc
return domain_info
+
+ def check_redirects(self, path_info, domain_info, environ):
+ """
+ Checks if the request matches any configured redirection. If
+ so, return a WSGI application that does the redirect; else
+ return None.
+ """
+ current_uri = construct_url(environ)
+ for redirect_info in domain_info.redirects:
+ if 'path' in redirect_info:
+ if redirect_info['path'] == path_info:
+ new = redirect_info['rewrite']
+ new = urlparse.urljoin(current_uri, redirect_info['rewrite'])
+ exc = httpexceptions.HTTPMovedPermanently(
+ headers=[('Location', new)])
+ return exc
+ elif 'prefix' in redirect_info:
+ assert redirect_info['prefix'].endswith('/')
+ new_uri = None
+ if path_info == redirect_info['prefix'][:-1]:
+ new_uri = redirect_info['rewrite'] + '/'
+ elif path_info.startswith(redirect_info['prefix']):
+ new_uri = redirect_info['rewrite']
+ if not new_uri.endswith('/'):
+ new_uri += '/'
+ new_uri += path_info[len(redirect_info['prefix']):]
+ if new_uri is not None:
+ new_uri = urlparse.urljoin(current_uri, new_uri)
+ exc = httpexceptions.HTTPMovedPermanently(
+ headers=[('Location', new_uri)])
+ return exc
+ return None
+
+ def set_additional_headers(self, domain_info, environ):
+ """
+ Set any additional headers that the domain has been configured
+ to send.
+ """
+ for header_name, header_value in domain_info.additional_request_headers:
+ header_name = 'HTTP_%s' % header_name.upper().replace('-', '_')
+ environ[header_name] = header_value
+
+ def match_remote_uri(self, path_info, domain_info, environ):
+ """
+ Look at the ``domain_info.remote_uris`` and what remote_uri
+ this request matches, returning that remote_uri (or None if
+ nothing is found).
+
+ Also calls ``find_remote_uri`` if configured.
+ """
+ remote_uri = None
+
+ for remote_uri_info in domain_info.remote_uris:
+ path = str(remote_uri_info['path'])
+ if not path.endswith('/'):
+ path += '/'
+ if path_info + '/' == path:
+ exc = httpexceptions.HTTPMovedPermanently(
+ headers=[('location', construct_url(environ, path_info=path_info+'/'))])
+ raise exc
+ if path_info.startswith(path):
+ # Found a match
+ remote_uri = remote_uri_info.get('remote_uri')
+ environ['SCRIPT_NAME'] += path[:-1]
+ environ['PATH_INFO'] = path_info[len(path)-1:]
+ if self.find_remote_uri:
+ remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf)
+ return remote_uri
+ if self.find_remote_uri:
+ # Last change for find_remote_uri to do something
+ remote_uri = self.find_remote_uri(remote_uri, None, environ, self.app_conf)
+ return remote_uri
More information about the z3-checkins
mailing list