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

Changeset 1691

Show
Ignore:
Timestamp:
06/24/07 00:41:44
Author:
fumanchu
Message:

Moved most of cpserver into a new restsrv.servers module.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/_cpserver.py

    r1683 r1691  
    1 """Manage an HTTP server with CherryPy.""" 
     1"""Manage HTTP servers with CherryPy.""" 
    22 
    33import socket 
    4 import threading 
    5 import time 
    64 
    75import cherrypy 
    86from cherrypy.lib import attributes 
    9  
    10  
    11 def client_host(server_host): 
    12     """Return the host on which a client can connect to the given listener.""" 
    13     if server_host == '0.0.0.0': 
    14         # 0.0.0.0 is INADDR_ANY, which should answer on localhost. 
    15         return '127.0.0.1' 
    16     if server_host == '::': 
    17         # :: is IN6ADDR_ANY, which should answer on localhost. 
    18         return '::1' 
    19     return server_host 
     7from cherrypy.restsrv.servers import * 
    208 
    219 
     
    9381     
    9482    def __init__(self): 
    95         self.httpservers = {} 
    96         self.interrupt = None 
     83        self.mgr = ServerManager(cherrypy.engine) 
     84     
     85    def _get_httpservers(self): 
     86        return self.mgr.httpservers 
     87    def _set_httpservers(self, value): 
     88        self.mgr.httpservers = value 
     89    httpservers = property(_get_httpservers, _set_httpservers) 
    9790     
    9891    def quickstart(self, server=None): 
     
    10497        """ 
    10598        httpserver, bind_addr = self.httpserver_from_self(server) 
    106         self.httpservers[httpserver] = bind_addr 
    107         self.start() 
     99        self.mgr.httpservers[httpserver] = bind_addr 
     100        self.mgr.start() 
    108101     
    109102    def httpserver_from_self(self, httpserver=None): 
     
    126119    def start(self): 
    127120        """Start all registered HTTP servers.""" 
    128         self.interrupt = None 
    129         if not self.httpservers: 
    130             raise ValueError("No HTTP servers have been created. " 
    131                              "Try server.quickstart instead.") 
    132         for httpserver in self.httpservers: 
    133             self._start_http(httpserver) 
    134         cherrypy.engine.subscribe('stop', self.stop) 
    135      
    136     def _start_http(self, httpserver): 
    137         """Start the given httpserver in a new thread.""" 
    138         scheme = "http" 
    139         if getattr(httpserver, "ssl_certificate", None): 
    140             scheme = "https" 
    141         bind_addr = self.httpservers[httpserver] 
    142         if isinstance(bind_addr, tuple): 
    143             wait_for_free_port(*bind_addr) 
    144             host, port = bind_addr 
    145             on_what = "%s://%s:%s/" % (scheme, host, port) 
    146         else: 
    147             on_what = "socket file: %s" % bind_addr 
    148          
    149         t = threading.Thread(target=self._start_http_thread, args=(httpserver,)) 
    150         t.setName("CPHTTPServer " + t.getName()) 
    151         t.start() 
    152          
    153         self.wait(httpserver) 
    154         cherrypy.log("Serving %s on %s" % (scheme.upper(), on_what), 'HTTP') 
    155      
    156     def _start_http_thread(self, httpserver): 
    157         """HTTP servers MUST be started in new threads, so that the 
    158         main thread persists to receive KeyboardInterrupt's. If an 
    159         exception is raised in the httpserver's thread then it's 
    160         trapped here, and the engine (and therefore our httpservers) 
    161         are shut down. 
    162         """ 
    163         try: 
    164             httpserver.start() 
    165         except KeyboardInterrupt, exc: 
    166             cherrypy.log("<Ctrl-C> hit: shutting down HTTP servers", "SERVER") 
    167             self.interrupt = exc 
    168             cherrypy.engine.stop() 
    169         except SystemExit, exc: 
    170             cherrypy.log("SystemExit raised: shutting down HTTP servers", "SERVER") 
    171             self.interrupt = exc 
    172             cherrypy.engine.stop() 
    173             raise 
    174         except: 
    175             import sys 
    176             self.interrupt = sys.exc_info()[1] 
    177             cherrypy.log("Error in HTTP server: shutting down", "SERVER", 
    178                          traceback=True) 
    179             cherrypy.engine.stop() 
    180             raise 
     121        self.mgr.start() 
    181122     
    182123    def wait(self, httpserver=None): 
     
    185126        If no httpserver is specified, wait for all registered httpservers. 
    186127        """ 
    187         if httpserver is None: 
    188             httpservers = self.httpservers.items() 
    189         else: 
    190             httpservers = [(httpserver, self.httpservers[httpserver])] 
    191          
    192         for httpserver, bind_addr in httpservers: 
    193             while not (getattr(httpserver, "ready", False) or self.interrupt): 
    194                 time.sleep(.1) 
    195             if self.interrupt: 
    196                 raise self.interrupt 
    197              
    198             # Wait for port to be occupied 
    199             if isinstance(bind_addr, tuple): 
    200                 host, port = bind_addr 
    201                 wait_for_occupied_port(host, port) 
     128        self.mgr.wait(httpserver) 
    202129     
    203130    def stop(self): 
    204131        """Stop all HTTP servers.""" 
    205         for httpserver, bind_addr in self.httpservers.items(): 
    206             try: 
    207                 httpstop = httpserver.stop 
    208             except AttributeError: 
    209                 pass 
    210             else: 
    211                 # httpstop() MUST block until the server is *truly* stopped. 
    212                 httpstop() 
    213                 if isinstance(bind_addr, tuple): 
    214                     wait_for_free_port(*bind_addr) 
    215                 cherrypy.log("HTTP Server shut down", "HTTP") 
     132        self.mgr.stop() 
    216133     
    217134    def restart(self): 
    218135        """Restart all HTTP servers.""" 
    219         self.stop() 
    220         self.start() 
     136        self.mgr.restart() 
    221137     
    222138    def base(self): 
     
    245161        return "%s://%s" % (scheme, host) 
    246162 
    247  
    248 def check_port(host, port): 
    249     """Raise an error if the given port is not free on the given host.""" 
    250     if not host: 
    251         raise ValueError("Host values of '' or None are not allowed.") 
    252     host = client_host(host) 
    253     port = int(port) 
    254      
    255     # AF_INET or AF_INET6 socket 
    256     # Get the correct address family for our host (allows IPv6 addresses) 
    257     for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, 
    258                                   socket.SOCK_STREAM): 
    259         af, socktype, proto, canonname, sa = res 
    260         s = None 
    261         try: 
    262             s = socket.socket(af, socktype, proto) 
    263             # See http://groups.google.com/group/cherrypy-users/ 
    264             #        browse_frm/thread/bbfe5eb39c904fe0 
    265             s.settimeout(1.0) 
    266             s.connect((host, port)) 
    267             s.close() 
    268             raise IOError("Port %s is in use on %s; perhaps the previous " 
    269                           "httpserver did not shut down properly." % 
    270                           (repr(port), repr(host))) 
    271         except socket.error: 
    272             if s: 
    273                 s.close() 
    274  
    275  
    276 def wait_for_free_port(host, port): 
    277     """Wait for the specified port to become free (drop requests).""" 
    278     if not host: 
    279         raise ValueError("Host values of '' or None are not allowed.") 
    280      
    281     for trial in xrange(50): 
    282         try: 
    283             check_port(host, port) 
    284         except IOError: 
    285             # Give the old server thread time to free the port. 
    286             time.sleep(.1) 
    287         else: 
    288             return 
    289      
    290     msg = "Port %s not free on %s" % (repr(port), repr(host)) 
    291     cherrypy.log(msg, 'HTTP') 
    292     raise IOError(msg) 
    293  
    294 def wait_for_occupied_port(host, port): 
    295     """Wait for the specified port to become active (receive requests).""" 
    296     if not host: 
    297         raise ValueError("Host values of '' or None are not allowed.") 
    298      
    299     for trial in xrange(50): 
    300         try: 
    301             check_port(host, port) 
    302         except IOError: 
    303             return 
    304         else: 
    305             time.sleep(.1) 
    306      
    307     msg = "Port %s not bound on %s" % (repr(port), repr(host)) 
    308     cherrypy.log(msg, 'HTTP') 
    309     raise IOError(msg) 
  • trunk/cherrypy/restsrv/__init__.py

    r1690 r1691  
    1212 
    1313from cherrypy.restsrv.wspbus import bus 
    14 from cherrypy.restsrv import plugins 
     14from cherrypy.restsrv import plugins, servers 

Hosted by WebFaction

Log in as guest/cpguest to create tickets