Robert Brewer avatar Robert Brewer committed 6a3a587

New _cpwsgi.make_app function for creating isolated WSGI application callables. You should only need to use it if two WSGI apps share the same script_name, or if you use a WSGI tool which expects a separate callable for each app.

Comments (0)

Files changed (3)

             # Get the 'Host' header, so we can do HTTPRedirects properly.
             self.process_headers()
             
+            if self.app is None:
+                # Some interfaces (like WSGI) may have already set self.app.
+                # If not, look up the app for this path.
+                self.script_name = r = cherrypy.tree.script_name(self.path)
+                if r is None:
+                    raise cherrypy.NotFound()
+                self.app = cherrypy.tree.apps[r]
+            
             # path_info should be the path from the
             # app root (script_name) to the handler.
-            self.script_name = r = cherrypy.tree.script_name(self.path)
-            if r is None:
-                raise cherrypy.NotFound()
-            self.app = cherrypy.tree.apps[r]
-            self.path_info = self.path[len(r.rstrip("/")):]
+            self.path_info = self.path[len(self.script_name.rstrip("/")):]
             
             # Loop to allow for InternalRedirect.
             pi = self.path_info
         pass
 
 
-def wsgiApp(environ, start_response):
-    """The WSGI 'application object' for CherryPy."""
-    
-    # Trap screen output from BaseHTTPRequestHandler.log_message()
-    if not cherrypy.config.get('log_to_screen'):
-        sys.stderr = NullWriter()
-    
+def _wsgi_callable(environ, start_response, app=None):
     request = None
     try:
         env = environ.get
         request.multithread = environ['wsgi.multithread']
         request.multiprocess = environ['wsgi.multiprocess']
         request.wsgi_environ = environ
+        
+        if app:
+            request.app = app
+            request.script_name = app.script_name
+        
         response = request.run(request_line(environ),
                                translate_headers(environ),
                                environ['wsgi.input'])
                 chunk = chunk.encode("ISO-8859-1")
             yield chunk
 
+def wsgiApp(environ, start_response):
+    """The WSGI 'application object' for CherryPy.
+    
+    Use this as the same WSGI callable for all your CP apps.
+    """
+    return _wsgi_callable(environ, start_response)
 
-# Server components.
+def make_app(app):
+    """Factory for making separate WSGI 'application objects' for each CP app.
+    
+    Example:
+        # 'app' will be a CherryPy application object
+        app = cherrypy.tree.mount(Root(), "/", localconf)
+        
+        # 'wsgi_app' will be a WSGI application
+        wsgi_app = _cpwsgi.make_app(app)
+    """
+    def single_app(environ, start_response):
+        return _wsgi_callable(environ, start_response, app)
+    return single_app
+
+
+
+#                            Server components                            #
 
 
 class CPHTTPRequest(_cpwsgiserver.HTTPRequest):
         if sockFile:
             bind_addr = sockFile
         else:
-            bind_addr = (conf('server.socket_host'), conf('server.socket_port'))
+            bind_addr = (conf('server.socket_host'),
+                         conf('server.socket_port'))
         
         apps = [(base, wsgiApp) for base in cherrypy.tree.apps]
         
         # The setup functions probably mounted new apps.
         # Tell our server about them.
         apps = []
-        for base in cherrypy.tree.apps:
+        for base, app in cherrypy.tree.apps.iteritems():
             if base == "/":
                 base = ""
             apps.append((base, _cpwsgi.wsgiApp))
+##            # We could use the following line, but it breaks test_tutorials
+##            apps.append((base, _cpwsgi.make_app(app)))
         apps.sort()
         apps.reverse()
         cherrypy.server.httpserver.mount_points = apps
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.