[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