Example #1
0
    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()
Example #3
0
	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())
Example #4
0
    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())
Example #5
0
    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)
Example #8
0
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, "")
Example #9
0
 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)
Example #10
0
	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)