def testPartialWrite(self): written = bytearray() class PartialWriter: def write(self, b): partial = b[:7] written.extend(partial) return len(partial) def flush(self): pass environ = {"SERVER_PROTOCOL": "HTTP/1.0"} h = SimpleHandler(BytesIO(), PartialWriter(), sys.stderr, environ) msg = "should not do partial writes" with self.assertWarnsRegex(DeprecationWarning, msg): h.run(hello_app) self.assertEqual( b"HTTP/1.0 200 OK\r\n" b"Content-Type: text/plain\r\n" b"Date: Mon, 05 Jun 2006 18:49:54 GMT\r\n" b"Content-Length: 13\r\n" b"\r\n" b"Hello, world!", written, )
def handle_one_request(self): self.raw_requestline = self.rfile.readline() if not self.raw_requestline: self.close_connection = 1 return if not self.parse_request(): # An error code has been sent, just exit return for prefix in self.server.wsgi_mods: if self.path.startswith(prefix): logger.debug('before wsgi SimpleHandler') try: handler = SimpleHandler(self.rfile, self.wfile, self.get_stderr(), self.get_environ(prefix)) handler.request_handler = self handler.run(self.server.wsgi_mods[prefix]) except Exception as e: logger.exception(e) logger.debug('after wsgi SimpleHandler') return mname = 'do_' + self.command if not hasattr(self, mname): self.send_error(501, "Unsupported method (%r)" % self.command) return method = getattr(self, mname) method()
def handle(self): self.raw_requestline = self.rfile.readline() if not self.parse_request(): # An error code has been sent, just exit return handler = SimpleHandler( self.rfile, self.wfile, self.get_stderr(), self.get_environ() ) handler.request_handler = self # backpointer for logging handler.run(self.server.get_app())
def testClientConnectionTerminations(self): environ = {"SERVER_PROTOCOL": "HTTP/1.0"} for exception in ( ConnectionAbortedError, BrokenPipeError, ConnectionResetError, ): with self.subTest(exception=exception): class AbortingWriter: def write(self, b): raise exception stderr = StringIO() h = SimpleHandler(BytesIO(), AbortingWriter(), stderr, environ) h.run(hello_app) self.assertFalse(stderr.getvalue())
def handle(self): """Handle a single HTTP request""" self.raw_requestline = self.rfile.readline(65537) if len(self.raw_requestline) > 65536: self.requestline = '' self.request_version = '' self.command = '' self.send_error(414) return if not self.parse_request(): # An error code has been sent, just exit return handler = SimpleHandler( self.rfile, self.wfile, self.get_stderr(), self.get_environ() ) handler.request_handler = self # backpointer for logging handler.run(self.server.get_app())
def testDontResetInternalStateOnException(self): class CustomException(ValueError): pass # We are raising CustomException here to trigger an exception # during the execution of SimpleHandler.finish_response(), so # we can easily test that the internal state of the handler is # preserved in case of an exception. class AbortingWriter: def write(self, b): raise CustomException stderr = StringIO() environ = {"SERVER_PROTOCOL": "HTTP/1.0"} h = SimpleHandler(BytesIO(), AbortingWriter(), stderr, environ) h.run(hello_app) self.assertIn("CustomException", stderr.getvalue()) # Test that the internal state of the handler is preserved. self.assertIsNotNone(h.result) self.assertIsNotNone(h.headers) self.assertIsNotNone(h.status) self.assertIsNotNone(h.environ)
def testPartialWrite(self): written = bytearray() class PartialWriter: def write(self, b): partial = b[:7] written.extend(partial) return len(partial) def flush(self): pass environ = {"SERVER_PROTOCOL": "HTTP/1.0"} h = SimpleHandler(BytesIO(), PartialWriter(), sys.stderr, environ) msg = "should not do partial writes" with self.assertWarnsRegex(DeprecationWarning, msg): h.run(hello_app) self.assertEqual( b"HTTP/1.0 200 OK\r\n" b"Content-Type: text/plain\r\n" b"Date: Mon, 05 Jun 2006 18:49:54 GMT\r\n" b"Content-Length: 13\r\n" b"\r\n" b"Hello, world!", written)
def wsgi_server(application, conn): '''WSGI handler based on the Python wsgiref SimpleHandler. A WSGI application should return a iterable op StringTypes. Any encoding must be handled by the WSGI application itself. ''' # TODO - this wsgi handler executes the application and renders a page in # memory completely before returning it as a response to the client. # Thus, it does not "stream" the result back to the client. It should be # possible though. The SimpleHandler accepts file-like stream objects. So, # it should be just a matter of connecting 0MQ requests/response streams # to the SimpleHandler requests and response streams. However, the Python # API for Mongrel2 doesn't seem to support file-like stream objects for # requests and responses. Unless I have missed something. # setup connection handler # sender_id is automatically generated # so that each handler instance is uniquely identified while True: debug("WAITING FOR REQUEST") # receive a request req = conn.recv() if DEBUG: debug("REQUEST HEADERS: %r\n" % req.headers) debug("REQUEST BODY: %r\n" % req.body) if req.is_disconnect(): print("DISCONNECT") continue # effectively ignore the disconnect from the client # json parsing gives us unicode instead of ascii. headers = dict((key.encode('ascii'), value.encode('ascii')) for (key, value) in req.headers.items()) env = {} add_request_metavariables(env, headers) add_http_variables(env, headers) debug("ENVIRON: %r\n" % env) # SimpleHandler needs file-like stream objects for # requests, errors and reponses reqIO = StringIO(req.body) errIO = StringIO() respIO = StringIO() # execute the application simple_handler = SimpleHandler(reqIO, respIO, errIO, env, multithread=False, multiprocess=False) simple_handler.run(application) response = respIO.getvalue() errors = errIO.getvalue() # return the response debug("RESPONSE: %r\n" % response) if errors: debug("ERRORS: %r" % errors) conn.reply(req, response) # Check if we should close the connection. respIO.seek(0) protocol = respIO.readline()[:8] msg = httplib.HTTPMessage(respIO, 0) http_1p1 = protocol == 'HTTP/1.1' conn_close = http_1p1 and msg.getheader("Connection") == "close" keep_alive = http_1p1 or msg.getheader("Connection") == "Keep-Alive" if conn_close or not keep_alive: debug("EXPLICITLY CLOSING CONNECTION") conn.reply(req, "")
def handleWSGI(stdin, stderr, stdout, environ): handler = SimpleHandler(stdin, stderr, stdout, environ.vars, multithread, multiprocess) handler.run_once = run_once handler.server_software = environ.vars["SERVER_SOFTWARE"] handler.run(app)
def handle_wsgi_request(stdin, stdout, stderr, environ): handler = SimpleHandler(stdin.buffer, stdout.buffer, stderr, environ.vars, environ.server.multithread, environ.server.multiprocess) handler.run_once = not environ.server.multiconnection handler.server_software = environ.server.software handler.run(app)