Index: third_party/cherrypy/_cpnative_server.py |
=================================================================== |
--- third_party/cherrypy/_cpnative_server.py (revision 0) |
+++ third_party/cherrypy/_cpnative_server.py (revision 0) |
@@ -0,0 +1,149 @@ |
+"""Native adapter for serving CherryPy via its builtin server.""" |
+ |
+import logging |
+import sys |
+ |
+import cherrypy |
+from cherrypy._cpcompat import BytesIO |
+from cherrypy._cperror import format_exc, bare_error |
+from cherrypy.lib import httputil |
+from cherrypy import wsgiserver |
+ |
+ |
+class NativeGateway(wsgiserver.Gateway): |
+ |
+ recursive = False |
+ |
+ def respond(self): |
+ req = self.req |
+ try: |
+ # Obtain a Request object from CherryPy |
+ local = req.server.bind_addr |
+ local = httputil.Host(local[0], local[1], "") |
+ remote = req.conn.remote_addr, req.conn.remote_port |
+ remote = httputil.Host(remote[0], remote[1], "") |
+ |
+ scheme = req.scheme |
+ sn = cherrypy.tree.script_name(req.uri or "/") |
+ if sn is None: |
+ self.send_response('404 Not Found', [], ['']) |
+ else: |
+ app = cherrypy.tree.apps[sn] |
+ method = req.method |
+ path = req.path |
+ qs = req.qs or "" |
+ headers = req.inheaders.items() |
+ rfile = req.rfile |
+ prev = None |
+ |
+ try: |
+ redirections = [] |
+ while True: |
+ request, response = app.get_serving( |
+ local, remote, scheme, "HTTP/1.1") |
+ request.multithread = True |
+ request.multiprocess = False |
+ request.app = app |
+ request.prev = prev |
+ |
+ # Run the CherryPy Request object and obtain the response |
+ try: |
+ request.run(method, path, qs, req.request_protocol, headers, rfile) |
+ break |
+ except cherrypy.InternalRedirect: |
+ ir = sys.exc_info()[1] |
+ app.release_serving() |
+ prev = request |
+ |
+ if not self.recursive: |
+ if ir.path in redirections: |
+ raise RuntimeError("InternalRedirector visited the " |
+ "same URL twice: %r" % ir.path) |
+ else: |
+ # Add the *previous* path_info + qs to redirections. |
+ if qs: |
+ qs = "?" + qs |
+ redirections.append(sn + path + qs) |
+ |
+ # Munge environment and try again. |
+ method = "GET" |
+ path = ir.path |
+ qs = ir.query_string |
+ rfile = BytesIO() |
+ |
+ self.send_response( |
+ response.output_status, response.header_list, |
+ response.body) |
+ finally: |
+ app.release_serving() |
+ except: |
+ tb = format_exc() |
+ #print tb |
+ cherrypy.log(tb, 'NATIVE_ADAPTER', severity=logging.ERROR) |
+ s, h, b = bare_error() |
+ self.send_response(s, h, b) |
+ |
+ def send_response(self, status, headers, body): |
+ req = self.req |
+ |
+ # Set response status |
+ req.status = str(status or "500 Server Error") |
+ |
+ # Set response headers |
+ for header, value in headers: |
+ req.outheaders.append((header, value)) |
+ if (req.ready and not req.sent_headers): |
+ req.sent_headers = True |
+ req.send_headers() |
+ |
+ # Set response body |
+ for seg in body: |
+ req.write(seg) |
+ |
+ |
+class CPHTTPServer(wsgiserver.HTTPServer): |
+ """Wrapper for wsgiserver.HTTPServer. |
+ |
+ wsgiserver 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 apply some attributes |
+ from config -> cherrypy.server -> HTTPServer. |
+ """ |
+ |
+ def __init__(self, server_adapter=cherrypy.server): |
+ self.server_adapter = server_adapter |
+ |
+ server_name = (self.server_adapter.socket_host or |
+ self.server_adapter.socket_file or |
+ None) |
+ |
+ wsgiserver.HTTPServer.__init__( |
+ self, server_adapter.bind_addr, NativeGateway, |
+ minthreads=server_adapter.thread_pool, |
+ maxthreads=server_adapter.thread_pool_max, |
+ server_name=server_name) |
+ |
+ self.max_request_header_size = self.server_adapter.max_request_header_size or 0 |
+ self.max_request_body_size = self.server_adapter.max_request_body_size or 0 |
+ self.request_queue_size = self.server_adapter.socket_queue_size |
+ self.timeout = self.server_adapter.socket_timeout |
+ self.shutdown_timeout = self.server_adapter.shutdown_timeout |
+ self.protocol = self.server_adapter.protocol_version |
+ self.nodelay = self.server_adapter.nodelay |
+ |
+ ssl_module = self.server_adapter.ssl_module or 'pyopenssl' |
+ if self.server_adapter.ssl_context: |
+ adapter_class = wsgiserver.get_ssl_adapter_class(ssl_module) |
+ self.ssl_adapter = adapter_class( |
+ self.server_adapter.ssl_certificate, |
+ self.server_adapter.ssl_private_key, |
+ self.server_adapter.ssl_certificate_chain) |
+ self.ssl_adapter.context = self.server_adapter.ssl_context |
+ elif self.server_adapter.ssl_certificate: |
+ adapter_class = wsgiserver.get_ssl_adapter_class(ssl_module) |
+ self.ssl_adapter = adapter_class( |
+ self.server_adapter.ssl_certificate, |
+ self.server_adapter.ssl_private_key, |
+ self.server_adapter.ssl_certificate_chain) |
+ |
+ |
Property changes on: third_party/cherrypy/_cpnative_server.py |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |