Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Ticket #461: routingWSGI.diff

  • _cpserver.py

    old new  
    77import warnings 
    88 
    99import cherrypy 
    10 from cherrypy import _cphttptools, filters, _cpwsgi 
     10from cherrypy import _cphttptools, filters 
    1111from cherrypy.lib import autoreload, profiler, cptools 
    1212 
    1313# Use a flag to indicate the state of the application server. 
     
    3535        self.on_start_thread_list = [] 
    3636        self.on_stop_server_list = [] 
    3737        self.on_stop_thread_list = [] 
    38  
     38         
    3939        # Backward compatibility: 
    4040        self.onStopServerList = [] 
    4141        self.onStartThreadList = [] 
    4242        self.onStartServerList = [] 
    4343        self.onStopThreadList = [] 
    44  
    45         self.wsgi_app = _cpwsgi.wsgiApp 
    46          
    47     def start(self, init_only = False, server_class = _missing, **kwargs): 
     44     
     45    def start(self, init_only = False, server_class = _missing, 
     46              server = None, **kwargs): 
    4847        """Main function. MUST be called from the main thread. 
    4948         
    5049        Set initOnly to True to keep this function from blocking. 
     
    6261         
    6362        conf = cherrypy.config.get 
    6463         
    65         if server_class is _missing: 
    66             server_class = conf("server.class", _missing) 
    67         if server_class is _missing: 
    68             import _cpwsgi 
    69             server_class = _cpwsgi.WSGIServer 
    70         elif server_class and isinstance(server_class, basestring): 
    71             # Dynamically load the class from the given string 
    72             server_class = cptools.attributes(server_class) 
     64        if server is None: 
     65            if server_class is _missing: 
     66                server_class = conf("server.class", _missing) 
     67            if server_class is _missing: 
     68                import _cpwsgi 
     69                server_class = _cpwsgi.WSGIServer 
     70            elif server_class and isinstance(server_class, basestring): 
     71                # Dynamically load the class from the given string 
     72                server_class = cptools.attributes(server_class) 
     73            self.httpserverclass = server_class 
     74            if server_class is not None: 
     75                self.httpserver = server_class() 
     76        else: 
     77            self.httpserverclass = server.__class__ 
     78            self.httpserver = server 
    7379         
    7480        self.blocking = not init_only 
    75         self.httpserverclass = server_class 
    7681         
    7782        # Hmmm...we *could* check config in _start instead, but I think 
    7883        # most people would like CP to fail before autoreload kicks in. 
     
    8186        # Autoreload, but check server_class. If None, we're not starting 
    8287        # our own webserver, and therefore could do Very Bad Things when 
    8388        # autoreload calls sys.exit. 
    84         if server_class is not None: 
     89        if server_class is None and server is None: 
     90            pass 
     91        else: 
    8592            if conf('autoreload.on', False): 
    8693                try: 
    8794                    freq = conf('autoreload.frequency', 1) 
     
    133140     
    134141    def start_http_server(self, blocking=True): 
    135142        """Start the requested HTTP server.""" 
    136         if self.httpserver is not None: 
    137             msg = ("You seem to have an HTTP server still running." 
    138                    "Please call server.stop_http_server() " 
    139                    "before continuing.") 
    140             warnings.warn(msg) 
    141          
    142         if self.httpserverclass is None: 
     143        if not self.httpserver: 
    143144            return 
    144145         
    145146        if cherrypy.config.get('server.socket_port'): 
     
    154155        else: 
    155156            on_what = "socket file: %s" % cherrypy.config.get('server.socket_file') 
    156157         
    157         # Instantiate the server. 
    158         if self.httpserverclass == _cpwsgi.WSGIServer: 
    159             self.httpserver = self.httpserverclass(self.wsgi_app) 
    160              
    161         else: 
    162             self.httpserver = self.httpserverclass() 
    163          
    164158        # HTTP servers MUST be started in a new thread, so that the 
    165159        # main thread persists to receive KeyboardInterrupt's. This 
    166160        # wrapper traps an interrupt in the http server's main thread 
     
    178172        cherrypy.log("Serving HTTP on %s" % on_what, 'HTTP') 
    179173     
    180174    def wait_for_http_ready(self): 
    181         if self.httpserverclass is not None: 
     175        if self.httpserver is not None: 
    182176            while not getattr(self.httpserver, "ready", True): 
    183177                time.sleep(.1) 
    184178             
  • _cpwsgi.py

    old new  
    164164     
    165165    _cpwsgiserver has been designed to not reference CherryPy in any way, 
    166166    so that it can be used in other frameworks and applications. Therefore, 
    167     we wrap it here
     167    we wrap it here, so we can set our own mount points from cherrypy.tree
    168168     
    169169    """ 
    170170     
    171171    RequestHandlerClass = CPHTTPRequest 
    172172     
    173     def __init__(self, app=wsgiApp): 
     173    def __init__(self): 
    174174        conf = cherrypy.config.get 
    175175         
    176176        sockFile = cherrypy.config.get('server.socket_file') 
     
    179179        else: 
    180180            bind_addr = (conf("server.socket_host"), conf("server.socket_port")) 
    181181         
     182        pts = cherrypy.tree.mount_points 
     183        if pts: 
     184            apps = [(base, wsgiApp) for base in pts.keys()] 
     185        else: 
     186            apps = [("", wsgiApp)] 
     187         
    182188        s = _cpwsgiserver.CherryPyWSGIServer 
    183         s.__init__(self, bind_addr, app
     189        s.__init__(self, bind_addr, apps
    184190                   conf("server.thread_pool"), 
    185191                   conf("server.socket_host"), 
    186192                   request_queue_size = conf('server.socket_queue_size'), 
  • _cpwsgiserver.py

    old new  
    6464        else: 
    6565            qs = "" 
    6666        self.environ["REQUEST_METHOD"] = method 
    67         self.environ["SCRIPT_NAME"] = "" 
    68         self.environ["PATH_INFO"] = path 
     67         
     68        for mount_point, wsgi_app in self.server.mount_points: 
     69            # The mount_points list should be sorted by length, descending. 
     70            if path.startswith(mount_point): 
     71                self.environ["SCRIPT_NAME"] = mount_point 
     72                self.environ["PATH_INFO"] = path[len(mount_point):] 
     73                self.wsgi_app = wsgi_app 
     74                break 
     75        else: 
     76            msg = "Not Found" 
     77            proto = self.environ.get("SERVER_PROTOCOL", "HTTP/1.0") 
     78            self.wfile.write("%s 404 %s\r\n" % (proto, msg)) 
     79            self.wfile.write("Content-Length: %s\r\n\r\n" % len(msg)) 
     80            self.wfile.write(msg) 
     81            self.wfile.flush() 
     82            self.ready = False 
     83            return 
     84         
    6985        self.environ["QUERY_STRING"] = qs 
    7086        self.environ["SERVER_PROTOCOL"] = version 
    7187        self.environ["SERVER_NAME"] = self.server.server_name 
     
    160176                    try: 
    161177                        request.parse_request() 
    162178                        if request.ready: 
    163                             response = self.server.wsgi_app(request.environ, 
    164                                                             request.start_response) 
     179                            response = request.wsgi_app(request.environ, 
     180                                                        request.start_response) 
    165181                            for line in response: 
    166182                                request.write(line) 
    167183                    except socket.error, e: 
     
    191207        be careful w/ max 
    192208        ''' 
    193209        self.requests = Queue.Queue(max) 
    194         self.wsgi_app = wsgi_app 
     210         
     211        if callable(wsgi_app): 
     212            # We've been handed a single wsgi_app, in CP-2.1 style. 
     213            # Assume it's mounted at "". 
     214            self.mount_points = [("", wsgi_app)] 
     215        else: 
     216            # We've been handed a list of (mount_point, wsgi_app) tuples, 
     217            # so that the server can call different wsgi_apps, and also 
     218            # correctly set SCRIPT_NAME. 
     219            self.mount_points = wsgi_app 
     220        self.mount_points.sort() 
     221        self.mount_points.reverse() 
     222         
    195223        self.bind_addr = bind_addr 
    196224        self.numthreads = numthreads or 1 
    197225        if not server_name: 
     
    286314    def stop(self): 
    287315        """Gracefully shutdown a server that is serving forever.""" 
    288316        self.ready = False 
    289         self.socket.close() 
     317        s = getattr(self, "socket", None) 
     318        if s and hasattr(s, "close"): 
     319            s.close() 
    290320         
    291321        # Must shut down threads here so the code that calls 
    292322        # this method can know when all threads are stopped. 
  • test/helper.py

    old new  
    6767    """Wrapper for WSGI server so we can test thrown errors.""" 
    6868     
    6969    def __init__(self): 
    70         _cpwsgi.WSGIServer.__init__(self, error_middleware) 
     70        _cpwsgi.WSGIServer.__init__(self) 
     71        self.mount_points = [(base, error_middleware) 
     72                             for base, wsgiapp in self.mount_points] 
    7173 
    7274 
    7375class CPWebCase(webtest.WebCase): 
  • test/test_core.py

    old new  
    631631        self.assertInBody(msg) 
    632632         
    633633        # Test server.throw_errors (ticket #186). 
    634         httpcls = cherrypy.server.httpserverclass 
    635         if httpcls: 
     634        s = cherrypy.server.httpserver 
     635        if s: 
    636636            self.getPage("/error/rethrow") 
    637637            self.assertBody("THROWN ERROR: ValueError") 
    638638        else: 
     
    836836        self.getPage("/maxrequestsize/index") 
    837837        self.assertBody("OK") 
    838838         
    839         httpcls = cherrypy.server.httpserverclass 
    840         if httpcls: 
     839        s = cherrypy.server.httpserver 
     840        if s: 
    841841            cherrypy.config.update({'server.max_request_header_size': 10}) 
    842842            self.getPage("/maxrequestsize/index") 
    843843            self.assertStatus("413 Request Entity Too Large") 
     
    865865        self.getPage('/maxrequestsize/upload', h, "POST", b) 
    866866        self.assertBody('Size: 5') 
    867867         
    868         httpcls = cherrypy.server.httpserverclass 
    869         if httpcls: 
     868        s = cherrypy.server.httpserver 
     869        if s: 
    870870            cherrypy.config.update({ 
    871871                '%s/maxrequestsize' % self.prefix(): {'server.max_request_body_size': 3}}) 
    872872            self.getPage('/maxrequestsize/upload', h, "POST", b) 
  • test/test_logdebuginfo_filter.py

    old new  
    3434        #self.assertInBody('Session data size') 
    3535 
    3636    def testBug326(self): 
    37         httpcls = cherrypy.server.httpserverclass 
    38         if httpcls and httpcls.__name__ == "WSGIServer": 
     37        from cherrypy import _cpwsgi 
     38        s = cherrypy.server.httpserver 
     39        if s and isinstance(s, _cpwsgi.WSGIServer): 
    3940            h = [("Content-type", "multipart/form-data; boundary=x"), 
    4041                 ("Content-Length", "110")] 
    4142            b = """--x 
     
    4647--x-- 
    4748""" 
    4849            cherrypy.config.update({ 
    49                 ('%s/bug326' % self.prefix): { 
     50                ('%s/bug326' % self.prefix()): { 
    5051                    'server.max_request_body_size': 3, 
    5152                    'server.environment': 'development', 
    5253                } 

Hosted by WebFaction

Log in as guest/cpguest to create tickets