Bundled cherrypy.
[smonitor.git] / monitor / cherrypy / _cpserver.py
blobc1695a669aac31384b161f0d890b75bca8e694e5
1 """Manage HTTP servers with CherryPy."""
3 import warnings
5 import cherrypy
6 from cherrypy.lib import attributes
7 from cherrypy._cpcompat import basestring
9 # We import * because we want to export check_port
10 # et al as attributes of this module.
11 from cherrypy.process.servers import *
14 class Server(ServerAdapter):
15 """An adapter for an HTTP server.
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::
21 cherrypy.server.socket_port = 80
22 cherrypy.quickstart()
23 """
25 socket_port = 8080
26 """The TCP port on which to listen for connections."""
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.
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.""")
47 socket_file = None
48 """If given, the name of the UNIX socket to use instead of TCP/IP.
50 When this option is not None, the `socket_host` and `socket_port` options
51 are ignored."""
53 socket_queue_size = 5
54 """The 'backlog' argument to socket.listen(); specifies the maximum number
55 of queued connections (default 5)."""
57 socket_timeout = 10
58 """The timeout in seconds for accepted connections (default 10)."""
60 shutdown_timeout = 5
61 """The time to wait for HTTP worker threads to clean up."""
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."""
68 thread_pool = 10
69 """The number of worker threads to start up in the pool."""
71 thread_pool_max = -1
72 """The maximum size of the worker-thread pool. Use -1 to indicate no limit."""
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"."""
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"."""
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."""
88 ssl_context = None
89 """When using PyOpenSSL, an instance of SSL.Context."""
91 ssl_certificate = None
92 """The filename of the SSL certificate to use."""
94 ssl_certificate_chain = None
95 """When using PyOpenSSL, the certificate chain to pass to
96 Context.load_verify_locations."""
98 ssl_private_key = None
99 """The filename of the private key to use with SSL."""
101 ssl_module = 'pyopenssl'
102 """The name of a registered SSL adaptation module to use with the builtin
103 WSGI server. Builtin options are 'builtin' (to use the SSL library built
104 into recent versions of Python) and 'pyopenssl' (to use the PyOpenSSL
105 project, which you must install separately). You may also register your
106 own classes in the wsgiserver.ssl_adapters dict."""
108 nodelay = True
109 """If True (the default since 3.1), sets the TCP_NODELAY socket option."""
111 wsgi_version = (1, 0)
112 """The WSGI version tuple to use with the builtin WSGI server.
113 The provided options are (1, 0) [which includes support for PEP 3333,
114 which declares it covers WSGI version 1.0.1 but still mandates the
115 wsgi.version (1, 0)] and ('u', 0), an experimental unicode version.
116 You may create and register your own experimental versions of the WSGI
117 protocol by adding custom classes to the wsgiserver.wsgi_gateways dict."""
119 def __init__(self):
120 self.bus = cherrypy.engine
121 self.httpserver = None
122 self.interrupt = None
123 self.running = False
125 def httpserver_from_self(self, httpserver=None):
126 """Return a (httpserver, bind_addr) pair based on self attributes."""
127 if httpserver is None:
128 httpserver = self.instance
129 if httpserver is None:
130 from cherrypy import _cpwsgi_server
131 httpserver = _cpwsgi_server.CPWSGIServer(self)
132 if isinstance(httpserver, basestring):
133 # Is anyone using this? Can I add an arg?
134 httpserver = attributes(httpserver)(self)
135 return httpserver, self.bind_addr
137 def start(self):
138 """Start the HTTP server."""
139 if not self.httpserver:
140 self.httpserver, self.bind_addr = self.httpserver_from_self()
141 ServerAdapter.start(self)
142 start.priority = 75
144 def _get_bind_addr(self):
145 if self.socket_file:
146 return self.socket_file
147 if self.socket_host is None and self.socket_port is None:
148 return None
149 return (self.socket_host, self.socket_port)
150 def _set_bind_addr(self, value):
151 if value is None:
152 self.socket_file = None
153 self.socket_host = None
154 self.socket_port = None
155 elif isinstance(value, basestring):
156 self.socket_file = value
157 self.socket_host = None
158 self.socket_port = None
159 else:
160 try:
161 self.socket_host, self.socket_port = value
162 self.socket_file = None
163 except ValueError:
164 raise ValueError("bind_addr must be a (host, port) tuple "
165 "(for TCP sockets) or a string (for Unix "
166 "domain sockets), not %r" % value)
167 bind_addr = property(_get_bind_addr, _set_bind_addr,
168 doc='A (host, port) tuple for TCP sockets or a str for Unix domain sockets.')
170 def base(self):
171 """Return the base (scheme://host[:port] or sock file) for this server."""
172 if self.socket_file:
173 return self.socket_file
175 host = self.socket_host
176 if host in ('0.0.0.0', '::'):
177 # 0.0.0.0 is INADDR_ANY and :: is IN6ADDR_ANY.
178 # Look up the host name, which should be the
179 # safest thing to spit out in a URL.
180 import socket
181 host = socket.gethostname()
183 port = self.socket_port
185 if self.ssl_certificate:
186 scheme = "https"
187 if port != 443:
188 host += ":%s" % port
189 else:
190 scheme = "http"
191 if port != 80:
192 host += ":%s" % port
194 return "%s://%s" % (scheme, host)