Commits

Robert Brewer committed 72c947a

Moved _wsgi_callable to _cptree, and we now import _cpwsgi as cherrypy.wsgi. Also made {{{App.__call__}}} route to {{{App.wsgiapp}}} so the latter can be replaced by user code (i.e. it's not a special method).

Comments (0)

Files changed (3)

cherrypy/__init__.py

 from cherrypy import _cptree
 tree = _cptree.Tree()
 from cherrypy._cptree import Application
+from cherrypy import _cpwsgi as wsgi
 from cherrypy import _cpengine
 engine = _cpengine.Engine()
 from cherrypy import _cpserver

cherrypy/_cptree.py

-from cherrypy import _cpconfig, _cplogging, _cpwsgi
+"""CherryPy Application and Tree objects."""
+
+import sys
+import cherrypy
+from cherrypy import _cpconfig, _cplogging
+from cherrypy._cperror import format_exc, bare_error
+from cherrypy.lib import http
 
 
 class Application(object):
             host += ":%s" % port
         return scheme + host + self.script_name
     
+    def wsgiapp(self, environ, start_response):
+        # This is here instead of __call__ because it's really hard
+        # to overwrite special methods like __call__ per instance.
+        return wsgi_handler(environ, start_response, app=self)
+    
     def __call__(self, environ, start_response):
-        return _cpwsgi._wsgi_callable(environ, start_response, app=self)
+        return self.wsgiapp(environ, start_response)
+
+
+headerNames = {'HTTP_CGI_AUTHORIZATION': 'Authorization',
+               'CONTENT_LENGTH': 'Content-Length',
+               'CONTENT_TYPE': 'Content-Type',
+               'REMOTE_HOST': 'Remote-Host',
+               'REMOTE_ADDR': 'Remote-Addr',
+               }
+
+def translate_headers(environ):
+    """Translate CGI-environ header names to HTTP header names."""
+    for cgiName in environ:
+        # We assume all incoming header keys are uppercase already.
+        if cgiName in headerNames:
+            yield headerNames[cgiName], environ[cgiName]
+        elif cgiName[:5] == "HTTP_":
+            # Hackish attempt at recovering original header names.
+            translatedHeader = cgiName[5:].replace("_", "-")
+            yield translatedHeader, environ[cgiName]
+
+
+def wsgi_handler(environ, start_response, app):
+    request = None
+    try:
+        env = environ.get
+        local = http.Host('', int(env('SERVER_PORT', 80)),
+                          env('SERVER_NAME', ''))
+        remote = http.Host(env('REMOTE_ADDR', ''),
+                           int(env('REMOTE_PORT', -1)),
+                           env('REMOTE_HOST', ''))
+        request = cherrypy.engine.request(local, remote,
+                                          env('wsgi.url_scheme'),
+                                          env('ACTUAL_SERVER_PROTOCOL', "HTTP/1.1"))
+        
+        # LOGON_USER is served by IIS, and is the name of the
+        # user after having been mapped to a local account.
+        # Both IIS and Apache set REMOTE_USER, when possible.
+        request.login = env('LOGON_USER') or env('REMOTE_USER') or None
+        
+        request.multithread = environ['wsgi.multithread']
+        request.multiprocess = environ['wsgi.multiprocess']
+        request.wsgi_environ = environ
+        
+        request.app = app
+        
+        path = env('SCRIPT_NAME', '') + env('PATH_INFO', '')
+        response = request.run(environ['REQUEST_METHOD'], path,
+                               env('QUERY_STRING'),
+                               env('SERVER_PROTOCOL'),
+                               translate_headers(environ),
+                               environ['wsgi.input'])
+        s, h, b = response.status, response.header_list, response.body
+        exc = None
+    except (KeyboardInterrupt, SystemExit), ex:
+        try:
+            if request:
+                request.close()
+        except:
+            cherrypy.log(traceback=True)
+        request = None
+        raise ex
+    except:
+        if request and request.throw_errors:
+            raise
+        tb = format_exc()
+        cherrypy.log(tb)
+        if request and not request.show_tracebacks:
+            tb = ""
+        s, h, b = bare_error(tb)
+        exc = sys.exc_info()
+    
+    try:
+        start_response(s, h, exc)
+        for chunk in b:
+            # WSGI requires all data to be of type "str". This coercion should
+            # not take any time at all if chunk is already of type "str".
+            # If it's unicode, it could be a big performance hit (x ~500).
+            if not isinstance(chunk, str):
+                chunk = chunk.encode("ISO-8859-1")
+            yield chunk
+        if request:
+            request.close()
+        request = None
+    except (KeyboardInterrupt, SystemExit), ex:
+        try:
+            if request:
+                request.close()
+        except:
+            cherrypy.log(traceback=True)
+        request = None
+        raise ex
+    except:
+        cherrypy.log(traceback=True)
+        try:
+            if request:
+                request.close()
+        except:
+            cherrypy.log(traceback=True)
+        request = None
+        s, h, b = bare_error()
+        # CherryPy test suite expects bare_error body to be output,
+        # so don't call start_response (which, according to PEP 333,
+        # may raise its own error at that point).
+        for chunk in b:
+            if not isinstance(chunk, str):
+                chunk = chunk.encode("ISO-8859-1")
+            yield chunk
 
 
 class Tree(object):

cherrypy/_cpwsgi.py

 """WSGI interface (see PEP 333)."""
 
-import sys
-import cherrypy
+import cherrypy as _cherrypy
 from cherrypy import _cpwsgiserver
-from cherrypy._cperror import format_exc, bare_error
-from cherrypy.lib import http
+from cherrypy.lib import http as _http
 
 
-headerNames = {'HTTP_CGI_AUTHORIZATION': 'Authorization',
-               'CONTENT_LENGTH': 'Content-Length',
-               'CONTENT_TYPE': 'Content-Type',
-               'REMOTE_HOST': 'Remote-Host',
-               'REMOTE_ADDR': 'Remote-Addr',
-               }
-
-def translate_headers(environ):
-    """Translate CGI-environ header names to HTTP header names."""
-    for cgiName in environ:
-        # We assume all incoming header keys are uppercase already.
-        if cgiName in headerNames:
-            yield headerNames[cgiName], environ[cgiName]
-        elif cgiName[:5] == "HTTP_":
-            # Hackish attempt at recovering original header names.
-            translatedHeader = cgiName[5:].replace("_", "-")
-            yield translatedHeader, environ[cgiName]
-
-
-def _wsgi_callable(environ, start_response, app):
-    request = None
-    try:
-        env = environ.get
-        local = http.Host('', int(env('SERVER_PORT', 80)),
-                          env('SERVER_NAME', ''))
-        remote = http.Host(env('REMOTE_ADDR', ''),
-                           int(env('REMOTE_PORT', -1)),
-                           env('REMOTE_HOST', ''))
-        request = cherrypy.engine.request(local, remote,
-                                          env('wsgi.url_scheme'),
-                                          env('ACTUAL_SERVER_PROTOCOL', "HTTP/1.1"))
-        
-        # LOGON_USER is served by IIS, and is the name of the
-        # user after having been mapped to a local account.
-        # Both IIS and Apache set REMOTE_USER, when possible.
-        request.login = env('LOGON_USER') or env('REMOTE_USER') or None
-        
-        request.multithread = environ['wsgi.multithread']
-        request.multiprocess = environ['wsgi.multiprocess']
-        request.wsgi_environ = environ
-        
-        request.app = app
-        
-        path = env('SCRIPT_NAME', '') + env('PATH_INFO', '')
-        response = request.run(environ['REQUEST_METHOD'], path,
-                               env('QUERY_STRING'),
-                               env('SERVER_PROTOCOL'),
-                               translate_headers(environ),
-                               environ['wsgi.input'])
-        s, h, b = response.status, response.header_list, response.body
-        exc = None
-    except (KeyboardInterrupt, SystemExit), ex:
-        try:
-            if request:
-                request.close()
-        except:
-            cherrypy.log(traceback=True)
-        request = None
-        raise ex
-    except:
-        if request and request.throw_errors:
-            raise
-        tb = format_exc()
-        cherrypy.log(tb)
-        if request and not request.show_tracebacks:
-            tb = ""
-        s, h, b = bare_error(tb)
-        exc = sys.exc_info()
-    
-    try:
-        start_response(s, h, exc)
-        for chunk in b:
-            # WSGI requires all data to be of type "str". This coercion should
-            # not take any time at all if chunk is already of type "str".
-            # If it's unicode, it could be a big performance hit (x ~500).
-            if not isinstance(chunk, str):
-                chunk = chunk.encode("ISO-8859-1")
-            yield chunk
-        if request:
-            request.close()
-        request = None
-    except (KeyboardInterrupt, SystemExit), ex:
-        try:
-            if request:
-                request.close()
-        except:
-            cherrypy.log(traceback=True)
-        request = None
-        raise ex
-    except:
-        cherrypy.log(traceback=True)
-        try:
-            if request:
-                request.close()
-        except:
-            cherrypy.log(traceback=True)
-        request = None
-        s, h, b = bare_error()
-        # CherryPy test suite expects bare_error body to be output,
-        # so don't call start_response (which, according to PEP 333,
-        # may raise its own error at that point).
-        for chunk in b:
-            if not isinstance(chunk, str):
-                chunk = chunk.encode("ISO-8859-1")
-            yield chunk
-
 
 #                            Server components                            #
 
 class CPHTTPRequest(_cpwsgiserver.HTTPRequest):
     
     def parse_request(self):
-        mhs = cherrypy.server.max_request_header_size
+        mhs = _cherrypy.server.max_request_header_size
         if mhs > 0:
-            self.rfile = http.SizeCheckWrapper(self.rfile, mhs)
+            self.rfile = _http.SizeCheckWrapper(self.rfile, mhs)
         
         try:
             _cpwsgiserver.HTTPRequest.parse_request(self)
-        except http.MaxSizeExceeded:
+        except _http.MaxSizeExceeded:
             self.simple_response("413 Request Entity Too Large")
-            cherrypy.log(traceback=True)
+            _cherrypy.log(traceback=True)
     
     def decode_chunked(self):
         """Decode the 'chunked' transfer coding."""
-        if isinstance(self.rfile, http.SizeCheckWrapper):
+        if isinstance(self.rfile, _http.SizeCheckWrapper):
             self.rfile = self.rfile.rfile
-        mbs = cherrypy.server.max_request_body_size
+        mbs = _cherrypy.server.max_request_body_size
         if mbs > 0:
-            self.rfile = http.SizeCheckWrapper(self.rfile, mbs)
+            self.rfile = _http.SizeCheckWrapper(self.rfile, mbs)
         try:
             return _cpwsgiserver.HTTPRequest.decode_chunked(self)
-        except http.MaxSizeExceeded:
+        except _http.MaxSizeExceeded:
             self.simple_response("413 Request Entity Too Large")
-            cherrypy.log(traceback=True)
+            _cherrypy.log(traceback=True)
             return False
 
 
     ConnectionClass = CPHTTPConnection
     
     def __init__(self):
-        server = cherrypy.server
+        server = _cherrypy.server
         sockFile = server.socket_file
         if sockFile:
             bind_addr = sockFile
         s = _cpwsgiserver.CherryPyWSGIServer
         # We could just pass cherrypy.tree, but by passing tree.apps,
         # we get correct SCRIPT_NAMEs as early as possible.
-        s.__init__(self, bind_addr, cherrypy.tree.apps.items(),
+        s.__init__(self, bind_addr, _cherrypy.tree.apps.items(),
                    server.thread_pool,
                    server.socket_host,
                    request_queue_size = server.socket_queue_size,
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.