OLD | NEW |
(Empty) | |
| 1 """Manage HTTP servers with CherryPy.""" |
| 2 |
| 3 import warnings |
| 4 |
| 5 import cherrypy |
| 6 from cherrypy.lib import attributes |
| 7 from cherrypy._cpcompat import basestring, py3k |
| 8 |
| 9 # We import * because we want to export check_port |
| 10 # et al as attributes of this module. |
| 11 from cherrypy.process.servers import * |
| 12 |
| 13 |
| 14 class Server(ServerAdapter): |
| 15 """An adapter for an HTTP server. |
| 16 |
| 17 You can set attributes (like socket_host and socket_port) |
| 18 on *this* object (which is probably cherrypy.server), and call |
| 19 quickstart. For example:: |
| 20 |
| 21 cherrypy.server.socket_port = 80 |
| 22 cherrypy.quickstart() |
| 23 """ |
| 24 |
| 25 socket_port = 8080 |
| 26 """The TCP port on which to listen for connections.""" |
| 27 |
| 28 _socket_host = '127.0.0.1' |
| 29 def _get_socket_host(self): |
| 30 return self._socket_host |
| 31 def _set_socket_host(self, value): |
| 32 if value == '': |
| 33 raise ValueError("The empty string ('') is not an allowed value. " |
| 34 "Use '0.0.0.0' instead to listen on all active " |
| 35 "interfaces (INADDR_ANY).") |
| 36 self._socket_host = value |
| 37 socket_host = property(_get_socket_host, _set_socket_host, |
| 38 doc="""The hostname or IP address on which to listen for connections. |
| 39 |
| 40 Host values may be any IPv4 or IPv6 address, or any valid hostname. |
| 41 The string 'localhost' is a synonym for '127.0.0.1' (or '::1', if |
| 42 your hosts file prefers IPv6). The string '0.0.0.0' is a special |
| 43 IPv4 entry meaning "any active interface" (INADDR_ANY), and '::' |
| 44 is the similar IN6ADDR_ANY for IPv6. The empty string or None are |
| 45 not allowed.""") |
| 46 |
| 47 socket_file = None |
| 48 """If given, the name of the UNIX socket to use instead of TCP/IP. |
| 49 |
| 50 When this option is not None, the `socket_host` and `socket_port` options |
| 51 are ignored.""" |
| 52 |
| 53 socket_queue_size = 5 |
| 54 """The 'backlog' argument to socket.listen(); specifies the maximum number |
| 55 of queued connections (default 5).""" |
| 56 |
| 57 socket_timeout = 10 |
| 58 """The timeout in seconds for accepted connections (default 10).""" |
| 59 |
| 60 shutdown_timeout = 5 |
| 61 """The time to wait for HTTP worker threads to clean up.""" |
| 62 |
| 63 protocol_version = 'HTTP/1.1' |
| 64 """The version string to write in the Status-Line of all HTTP responses, |
| 65 for example, "HTTP/1.1" (the default). Depending on the HTTP server used, |
| 66 this should also limit the supported features used in the response.""" |
| 67 |
| 68 thread_pool = 10 |
| 69 """The number of worker threads to start up in the pool.""" |
| 70 |
| 71 thread_pool_max = -1 |
| 72 """The maximum size of the worker-thread pool. Use -1 to indicate no limit."
"" |
| 73 |
| 74 max_request_header_size = 500 * 1024 |
| 75 """The maximum number of bytes allowable in the request headers. If exceeded
, |
| 76 the HTTP server should return "413 Request Entity Too Large".""" |
| 77 |
| 78 max_request_body_size = 100 * 1024 * 1024 |
| 79 """The maximum number of bytes allowable in the request body. If exceeded, |
| 80 the HTTP server should return "413 Request Entity Too Large".""" |
| 81 |
| 82 instance = None |
| 83 """If not None, this should be an HTTP server instance (such as |
| 84 CPWSGIServer) which cherrypy.server will control. Use this when you need |
| 85 more control over object instantiation than is available in the various |
| 86 configuration options.""" |
| 87 |
| 88 ssl_context = None |
| 89 """When using PyOpenSSL, an instance of SSL.Context.""" |
| 90 |
| 91 ssl_certificate = None |
| 92 """The filename of the SSL certificate to use.""" |
| 93 |
| 94 ssl_certificate_chain = None |
| 95 """When using PyOpenSSL, the certificate chain to pass to |
| 96 Context.load_verify_locations.""" |
| 97 |
| 98 ssl_private_key = None |
| 99 """The filename of the private key to use with SSL.""" |
| 100 |
| 101 if py3k: |
| 102 ssl_module = 'builtin' |
| 103 """The name of a registered SSL adaptation module to use with the builti
n |
| 104 WSGI server. Builtin options are: 'builtin' (to use the SSL library buil
t |
| 105 into recent versions of Python). You may also register your |
| 106 own classes in the wsgiserver.ssl_adapters dict.""" |
| 107 else: |
| 108 ssl_module = 'pyopenssl' |
| 109 """The name of a registered SSL adaptation module to use with the builti
n |
| 110 WSGI server. Builtin options are 'builtin' (to use the SSL library built |
| 111 into recent versions of Python) and 'pyopenssl' (to use the PyOpenSSL |
| 112 project, which you must install separately). You may also register your |
| 113 own classes in the wsgiserver.ssl_adapters dict.""" |
| 114 |
| 115 statistics = False |
| 116 """Turns statistics-gathering on or off for aware HTTP servers.""" |
| 117 |
| 118 nodelay = True |
| 119 """If True (the default since 3.1), sets the TCP_NODELAY socket option.""" |
| 120 |
| 121 wsgi_version = (1, 0) |
| 122 """The WSGI version tuple to use with the builtin WSGI server. |
| 123 The provided options are (1, 0) [which includes support for PEP 3333, |
| 124 which declares it covers WSGI version 1.0.1 but still mandates the |
| 125 wsgi.version (1, 0)] and ('u', 0), an experimental unicode version. |
| 126 You may create and register your own experimental versions of the WSGI |
| 127 protocol by adding custom classes to the wsgiserver.wsgi_gateways dict.""" |
| 128 |
| 129 def __init__(self): |
| 130 self.bus = cherrypy.engine |
| 131 self.httpserver = None |
| 132 self.interrupt = None |
| 133 self.running = False |
| 134 |
| 135 def httpserver_from_self(self, httpserver=None): |
| 136 """Return a (httpserver, bind_addr) pair based on self attributes.""" |
| 137 if httpserver is None: |
| 138 httpserver = self.instance |
| 139 if httpserver is None: |
| 140 from cherrypy import _cpwsgi_server |
| 141 httpserver = _cpwsgi_server.CPWSGIServer(self) |
| 142 if isinstance(httpserver, basestring): |
| 143 # Is anyone using this? Can I add an arg? |
| 144 httpserver = attributes(httpserver)(self) |
| 145 return httpserver, self.bind_addr |
| 146 |
| 147 def start(self): |
| 148 """Start the HTTP server.""" |
| 149 if not self.httpserver: |
| 150 self.httpserver, self.bind_addr = self.httpserver_from_self() |
| 151 ServerAdapter.start(self) |
| 152 start.priority = 75 |
| 153 |
| 154 def _get_bind_addr(self): |
| 155 if self.socket_file: |
| 156 return self.socket_file |
| 157 if self.socket_host is None and self.socket_port is None: |
| 158 return None |
| 159 return (self.socket_host, self.socket_port) |
| 160 def _set_bind_addr(self, value): |
| 161 if value is None: |
| 162 self.socket_file = None |
| 163 self.socket_host = None |
| 164 self.socket_port = None |
| 165 elif isinstance(value, basestring): |
| 166 self.socket_file = value |
| 167 self.socket_host = None |
| 168 self.socket_port = None |
| 169 else: |
| 170 try: |
| 171 self.socket_host, self.socket_port = value |
| 172 self.socket_file = None |
| 173 except ValueError: |
| 174 raise ValueError("bind_addr must be a (host, port) tuple " |
| 175 "(for TCP sockets) or a string (for Unix " |
| 176 "domain sockets), not %r" % value) |
| 177 bind_addr = property(_get_bind_addr, _set_bind_addr, |
| 178 doc='A (host, port) tuple for TCP sockets or a str for Unix domain socke
ts.') |
| 179 |
| 180 def base(self): |
| 181 """Return the base (scheme://host[:port] or sock file) for this server."
"" |
| 182 if self.socket_file: |
| 183 return self.socket_file |
| 184 |
| 185 host = self.socket_host |
| 186 if host in ('0.0.0.0', '::'): |
| 187 # 0.0.0.0 is INADDR_ANY and :: is IN6ADDR_ANY. |
| 188 # Look up the host name, which should be the |
| 189 # safest thing to spit out in a URL. |
| 190 import socket |
| 191 host = socket.gethostname() |
| 192 |
| 193 port = self.socket_port |
| 194 |
| 195 if self.ssl_certificate: |
| 196 scheme = "https" |
| 197 if port != 443: |
| 198 host += ":%s" % port |
| 199 else: |
| 200 scheme = "http" |
| 201 if port != 80: |
| 202 host += ":%s" % port |
| 203 |
| 204 return "%s://%s" % (scheme, host) |
| 205 |
OLD | NEW |