Source

CherryPyFixTicketUrls / _cpwsgi.py

Full commit
Robert Brewer 8f77d80 
Robert Brewer af448b7 
Robert Brewer d8e65d3 
Robert Brewer c6576d4 
Robert Brewer edc8c8e 
Robert Brewer e5716ae 
Robert Brewer ba51eef 
Robert Brewer af448b7 









Robert Brewer acd666d 
Robert Brewer af448b7 
Robert Brewer 880df6f 



Robert Brewer af448b7 



Robert Brewer ec49d44 
Robert Brewer 6a3a587 
Robert Brewer 819be25 
Robert Brewer af448b7 
Robert Brewer 61bb49a 
Robert Brewer 25739c0 





Robert Brewer 1ca639c 



Robert Brewer eceb4cb 
Robert Brewer 1ca639c 
Robert Brewer 61bb49a 

Christian Wyglen… 75f6e64 
Robert Brewer 6a3a587 



Robert Brewer eceb4cb 



Robert Brewer 61bb49a 

Remi Delon b3cf533 
Robert Brewer 819be25 
Robert Brewer 40100fe 







Robert Brewer 5d461e0 
Robert Brewer 8cd1230 
Robert Brewer e6bbd95 
Robert Brewer e5716ae 
Robert Brewer 5d461e0 
Robert Brewer 8cd1230 
Robert Brewer bbddf9e 
Robert Brewer e5716ae 
Robert Brewer 01f8067 
Robert Brewer 5d461e0 

Robert Brewer 01f8067 

Robert Brewer af448b7 


Robert Brewer 2f0adcd 

Robert Brewer 557d5d1 
Robert Brewer 819be25 

Robert Brewer 3fac06f 
Robert Brewer d6d9170 




Robert Brewer ef50908 
Robert Brewer 3fac06f 
Robert Brewer d6d9170 
Robert Brewer af448b7 
Robert Brewer ef50908 
Robert Brewer d6d9170 



Robert Brewer ef50908 
Robert Brewer 3fac06f 
Robert Brewer e5716ae 

Robert Brewer 7c60071 
Robert Brewer 758d621 
Robert Brewer af448b7 
Robert Brewer 2f0adcd 


Robert Brewer af448b7 
Robert Brewer 6a3a587 





Robert Brewer af448b7 
Robert Brewer 6a3a587 
















Robert Brewer af448b7 
Robert Brewer 03efe00 




Remi Delon b3cf533 
Robert Brewer 03efe00 
Robert Brewer cb8bcdd 
Robert Brewer ba51eef 
Robert Brewer 03efe00 



Robert Brewer ba51eef 
Robert Brewer 03efe00 
Robert Brewer eceb4cb 
Robert Brewer 03efe00 




Robert Brewer ef50908 
Robert Brewer 03efe00 


Christian Wyglen… 6a6a7b6 


Robert Brewer 03efe00 

Robert Brewer 35cf42d 
Robert Brewer ba51eef 
Robert Brewer 30481ba 

Robert Brewer 35cf42d 
Robert Brewer 03efe00 


Robert Brewer acd666d 




Robert Brewer 97ba492 
Robert Brewer acd666d 


Robert Brewer 03efe00 

Robert Brewer 97ba492 
Robert Brewer c6576d4 
Robert Brewer 03efe00 
Robert Brewer 30481ba 
Robert Brewer 03efe00 


Robert Brewer 6a3a587 

Robert Brewer 03efe00 
Robert Brewer 2444f62 
Robert Brewer 97ba492 
Robert Brewer 03efe00 
Robert Brewer 97ba492 
Robert Brewer 30481ba 

Remi Delon b3cf533 
Robert Brewer 49f0df2 
Robert Brewer 03efe00 
Robert Brewer eceb4cb 
Robert Brewer 03efe00 
"""A WSGI application interface (see PEP 333)."""

import sys
import cherrypy
from cherrypy import _cpwsgiserver
from cherrypy._cperror import format_exc, bare_error
from cherrypy.lib import 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=None):
    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'))
        
        # 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
        
        if app:
            request.app = app
        
        path = environ.get('SCRIPT_NAME', '') + environ.get('PATH_INFO', '')
        response = request.run(environ['REQUEST_METHOD'], path,
                               environ.get('QUERY_STRING'),
                               environ.get('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 cherrypy.config.get("throw_errors", False):
            raise
        tb = format_exc()
        cherrypy.log(tb)
        if not cherrypy.config.get("show_tracebacks", False):
            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

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)

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):
    
    def __init__(self, socket, addr, server):
        _cpwsgiserver.HTTPRequest.__init__(self, socket, addr, server)
        mhs = int(cherrypy.config.get('server.max_request_header_size',
                                      500 * 1024))
        if mhs > 0:
            self.rfile = http.SizeCheckWrapper(self.rfile, mhs)
    
    def parse_request(self):
        try:
            _cpwsgiserver.HTTPRequest.parse_request(self)
        except http.MaxSizeExceeded:
            msg = "Request Entity Too Large"
            self.wfile.write("%s 413 %s\r\n" % (self.server.protocol, msg))
            self.wfile.write("Content-Length: %s\r\n\r\n" % len(msg))
            self.wfile.write(msg)
            self.wfile.flush()
            self.ready = False
            
            cherrypy.log(traceback=True)
        else:
            if self.ready:
                # Request header is parsed
                script_name = self.environ.get('SCRIPT_NAME', '')
                path_info = self.environ.get('PATH_INFO', '')
                path = (script_name + path_info)
                if path == "*":
                    path = "global"
                
                if isinstance(self.rfile, http.SizeCheckWrapper):
                    # Unwrap the rfile
                    self.rfile = self.rfile.rfile
                self.environ["wsgi.input"] = self.rfile


class WSGIServer(_cpwsgiserver.CherryPyWSGIServer):
    
    """Wrapper for _cpwsgiserver.CherryPyWSGIServer.
    
    _cpwsgiserver has been designed to not reference CherryPy in any way,
    so that it can be used in other frameworks and applications. Therefore,
    we wrap it here, so we can set our own mount points from cherrypy.tree.
    
    """
    
    RequestHandlerClass = CPHTTPRequest
    
    def __init__(self):
        conf = cherrypy.config.get
        
        sockFile = conf('server.socket_file')
        if sockFile:
            bind_addr = sockFile
        else:
            bind_addr = (conf('server.socket_host'),
                         conf('server.socket_port'))
        
        apps = [(base, wsgiApp) for base in cherrypy.tree.apps]
        
        s = _cpwsgiserver.CherryPyWSGIServer
        s.__init__(self, bind_addr, apps,
                   conf('server.thread_pool'),
                   conf('server.socket_host'),
                   request_queue_size = conf('server.socket_queue_size'),
                   timeout = conf('server.socket_timeout'),
                   )
        s.protocol = conf('server.protocol_version', 'HTTP/1.0')