class TestHTTPProtocol(TestCase):
    """
    Tests that the HTTP protocol class correctly generates and parses messages.
    """

    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer)
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    def test_basic(self):
        """
        Tests basic HTTP parsing
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['http_version'], "1.1")
        self.assertEqual(message['method'], "GET")
        self.assertEqual(message['scheme'], "http")
        self.assertEqual(message['path'], "/te st-à/")
        self.assertEqual(message['query_string'], b"foo=+bar")
        self.assertEqual(message['headers'], [(b"host", b"somewhere.com")])
        self.assertFalse(message.get("body", None))
        self.assertTrue(message['reply_channel'])
        # Send back an example response
        self.factory.dispatch_reply(
            message['reply_channel'],
            {
                "status": 201,
                "status_text": b"Created",
                "content": b"OH HAI",
                "headers": [[b"X-Test", b"Boom!"]],
            }
        )
        # Make sure that comes back right on the protocol
        self.assertEqual(self.tr.value(), b"HTTP/1.1 201 Created\r\nTransfer-Encoding: chunked\r\nX-Test: Boom!\r\n\r\n6\r\nOH HAI\r\n0\r\n\r\n")

    def test_root_path_header(self):
        """
        Tests root path header handling
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"Daphne-Root-Path: /foobar%20/bar\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer, check root_path
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['root_path'], "/foobar /bar")
Пример #2
0
class TestHTTPProtocol(TestCase):
    """
    Tests that the HTTP protocol class correctly generates and parses messages.
    """
    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer)
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    def test_basic(self):
        """
        Tests basic HTTP parsing
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" + b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['http_version'], "1.1")
        self.assertEqual(message['method'], "GET")
        self.assertEqual(message['scheme'], "http")
        self.assertEqual(message['path'], "/te st-à/")
        self.assertEqual(message['query_string'], b"foo=+bar")
        self.assertEqual(message['headers'], [(b"host", b"somewhere.com")])
        self.assertFalse(message.get("body", None))
        self.assertTrue(message['reply_channel'])
        # Send back an example response
        self.factory.dispatch_reply(
            message['reply_channel'], {
                "status": 201,
                "status_text": b"Created",
                "content": b"OH HAI",
                "headers": [[b"X-Test", b"Boom!"]],
            })
        # Make sure that comes back right on the protocol
        self.assertEqual(
            self.tr.value(),
            b"HTTP/1.1 201 Created\r\nTransfer-Encoding: chunked\r\nX-Test: Boom!\r\n\r\n6\r\nOH HAI\r\n0\r\n\r\n"
        )

    def test_root_path_header(self):
        """
        Tests root path header handling
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" +
                                b"Daphne-Root-Path: /foobar%20/bar\r\n" +
                                b"\r\n")
        # Get the resulting message off of the channel layer, check root_path
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['root_path'], "/foobar /bar")
Пример #3
0
class TestHTTPProtocol(TestCase):
    """
    Tests that the HTTP protocol class correctly generates and parses messages.
    """

    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer)
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    def test_basic(self):
        """
        Tests basic HTTP parsing
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['http_version'], "1.1")
        self.assertEqual(message['method'], "GET")
        self.assertEqual(message['scheme'], "http")
        self.assertEqual(message['path'], "/te st-à/")
        self.assertEqual(message['query_string'], b"foo=+bar")
        self.assertEqual(message['headers'], [(b"host", b"somewhere.com")])
        self.assertFalse(message.get("body", None))
        self.assertTrue(message['reply_channel'])
        # Send back an example response
        self.factory.dispatch_reply(
            message['reply_channel'],
            {
                "status": 201,
                "status_text": b"Created",
                "content": b"OH HAI",
                "headers": [[b"X-Test", b"Boom!"]],
            }
        )
        # Make sure that comes back right on the protocol
        self.assertEqual(self.tr.value(), b"HTTP/1.1 201 Created\r\nTransfer-Encoding: chunked\r\nX-Test: Boom!\r\n\r\n6\r\nOH HAI\r\n0\r\n\r\n")

    def test_root_path_header(self):
        """
        Tests root path header handling
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"Daphne-Root-Path: /foobar%20/bar\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer, check root_path
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['root_path'], "/foobar /bar")

    def test_http_disconnect_sets_path_key(self):
        """
        Tests http disconnect has the path key set, see https://channels.readthedocs.io/en/latest/asgi.html#disconnect
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=bar HTTP/1.1\r\n" +
            b"Host: anywhere.com\r\n" +
            b"\r\n"
        )
        # Get the request message
        _, message = self.channel_layer.receive_many(["http.request"])

        # Send back an example response
        self.factory.dispatch_reply(
            message['reply_channel'],
            {
                "status": 200,
                "status_text": b"OK",
                "content": b"DISCO",
            }
        )

        # Get the disconnection notification
        _, disconnect_message = self.channel_layer.receive_many(["http.disconnect"])
        self.assertEqual(disconnect_message['path'], "/te st-à/")

    def test_x_forwarded_for_ignored(self):
        """
        Tests basic HTTP parsing
        """
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"X-Forwarded-For: 10.1.2.3\r\n" +
            b"X-Forwarded-Port: 80\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['client'], ['192.168.1.1', 54321])

    def test_x_forwarded_for_parsed(self):
        """
        Tests basic HTTP parsing
        """
        self.factory.proxy_forwarded_address_header = 'X-Forwarded-For'
        self.factory.proxy_forwarded_port_header = 'X-Forwarded-Port'
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"X-Forwarded-For: 10.1.2.3\r\n" +
            b"X-Forwarded-Port: 80\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 80])

    def test_x_forwarded_for_port_missing(self):
        """
        Tests basic HTTP parsing
        """
        self.factory.proxy_forwarded_address_header = 'X-Forwarded-For'
        self.factory.proxy_forwarded_port_header = 'X-Forwarded-Port'
        self.proto.dataReceived(
            b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
            b"Host: somewhere.com\r\n" +
            b"X-Forwarded-For: 10.1.2.3\r\n" +
            b"\r\n"
        )
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 0])
Пример #4
0
class TestHTTPProtocol(TestCase):
    """
    Tests that the HTTP protocol class correctly generates and parses messages.
    """
    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer)
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    def assertStartsWith(self, data, prefix):
        real_prefix = data[:len(prefix)]
        self.assertEqual(real_prefix, prefix)

    def test_basic(self):
        """
        Tests basic HTTP parsing
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /test/?foo=bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" + b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['http_version'], "1.1")
        self.assertEqual(message['method'], "GET")
        self.assertEqual(message['scheme'], "http")
        self.assertEqual(message['path'], b"/test/")
        self.assertEqual(message['query_string'], b"foo=bar")
        self.assertEqual(message['headers'], {"host": b"somewhere.com"})
        self.assertFalse(message.get("body", None))
        self.assertTrue(message['reply_channel'])
        # Send back an example response
        self.factory.dispatch_reply(
            message['reply_channel'], {
                "status": 201,
                "status_text": b"Created",
                "content": b"OH HAI",
                "headers": [["X-Test", b"Boom!"]],
            })
        # Make sure that comes back right on the protocol
        self.assertEqual(
            self.tr.value(),
            b"HTTP/1.1 201 Created\r\nTransfer-Encoding: chunked\r\nX-Test: Boom!\r\n\r\n6\r\nOH HAI\r\n0\r\n\r\n"
        )

    def test_custom_status_text(self):
        """
        Tests basic HTTP parsing
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /test/?foo=bar HTTP/1.0\r\n" + b"\r\n")
        # Send back an example response
        _, message = self.channel_layer.receive_many(["http.request"])
        self.factory.dispatch_reply(message['reply_channel'], {
            "status": 484,
            "status_text": b"Daphne Is Awesome",
        })
        # Make sure that comes back right on the protocol
        self.assertStartsWith(self.tr.value(),
                              b"HTTP/1.0 484 Daphne Is Awesome\r\n")
Пример #5
0
class TestHTTPProtocol(TestCase):
    """
    Tests that the HTTP protocol class correctly generates and parses messages.
    """
    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer)
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    def test_basic(self):
        """
        Tests basic HTTP parsing
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" + b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['http_version'], "1.1")
        self.assertEqual(message['method'], "GET")
        self.assertEqual(message['scheme'], "http")
        self.assertEqual(message['path'], "/te st-à/")
        self.assertEqual(message['query_string'], b"foo=+bar")
        self.assertEqual(message['headers'], [(b"host", b"somewhere.com")])
        self.assertFalse(message.get("body", None))
        self.assertTrue(message['reply_channel'])
        # Send back an example response
        self.factory.dispatch_reply(
            message['reply_channel'], {
                "status": 201,
                "status_text": b"Created",
                "content": b"OH HAI",
                "headers": [[b"X-Test", b"Boom!"]],
            })
        # Make sure that comes back right on the protocol
        self.assertEqual(
            self.tr.value(),
            b"HTTP/1.1 201 Created\r\nTransfer-Encoding: chunked\r\nX-Test: Boom!\r\n\r\n6\r\nOH HAI\r\n0\r\n\r\n"
        )

    def test_root_path_header(self):
        """
        Tests root path header handling
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" +
                                b"Daphne-Root-Path: /foobar%20/bar\r\n" +
                                b"\r\n")
        # Get the resulting message off of the channel layer, check root_path
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['root_path'], "/foobar /bar")

    def test_http_disconnect_sets_path_key(self):
        """
        Tests http disconnect has the path key set, see https://channels.readthedocs.io/en/latest/asgi.html#disconnect
        """
        # Send a simple request to the protocol
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=bar HTTP/1.1\r\n" +
                                b"Host: anywhere.com\r\n" + b"\r\n")
        # Get the request message
        _, message = self.channel_layer.receive_many(["http.request"])

        # Send back an example response
        self.factory.dispatch_reply(message['reply_channel'], {
            "status": 200,
            "status_text": b"OK",
            "content": b"DISCO",
        })

        # Get the disconnection notification
        _, disconnect_message = self.channel_layer.receive_many(
            ["http.disconnect"])
        self.assertEqual(disconnect_message['path'], "/te st-à/")

    def test_x_forwarded_for_ignored(self):
        """
        Tests basic HTTP parsing
        """
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" +
                                b"X-Forwarded-For: 10.1.2.3\r\n" +
                                b"X-Forwarded-Port: 80\r\n" + b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['client'], ['192.168.1.1', 54321])

    def test_x_forwarded_for_parsed(self):
        """
        Tests basic HTTP parsing
        """
        self.factory.proxy_forwarded_address_header = 'X-Forwarded-For'
        self.factory.proxy_forwarded_port_header = 'X-Forwarded-Port'
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" +
                                b"X-Forwarded-For: 10.1.2.3\r\n" +
                                b"X-Forwarded-Port: 80\r\n" + b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 80])

    def test_x_forwarded_for_port_missing(self):
        """
        Tests basic HTTP parsing
        """
        self.factory.proxy_forwarded_address_header = 'X-Forwarded-For'
        self.factory.proxy_forwarded_port_header = 'X-Forwarded-Port'
        self.proto.dataReceived(b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" +
                                b"Host: somewhere.com\r\n" +
                                b"X-Forwarded-For: 10.1.2.3\r\n" + b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 0])
Пример #6
0
class TestWebSocketProtocol(TestCase):
    """
    Tests that the HTTP protocol class correctly generates and parses messages.
    """
    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer)
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    def test_basic(self):
        # Send a simple request to the protocol
        self.proto.dataReceived(
            b"GET /chat HTTP/1.1\r\n"
            b"Host: somewhere.com\r\n"
            b"Upgrade: websocket\r\n"
            b"Connection: Upgrade\r\n"
            b"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
            b"Sec-WebSocket-Protocol: chat, superchat\r\n"
            b"Sec-WebSocket-Version: 13\r\n"
            b"Origin: http://example.com\r\n"
            b"\r\n")
        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive_many(["websocket.connect"])
        self.assertEqual(message['path'], "/chat")
        self.assertEqual(message['query_string'], "")
        self.assertEqual(sorted(message['headers']),
                         [(b'connection', b'Upgrade'),
                          (b'host', b'somewhere.com'),
                          (b'origin', b'http://example.com'),
                          (b'sec-websocket-key', b'x3JJHMbDL1EzLkh9GBhXDw=='),
                          (b'sec-websocket-protocol', b'chat, superchat'),
                          (b'sec-websocket-version', b'13'),
                          (b'upgrade', b'websocket')])
        self.assertTrue(message['reply_channel'].startswith("websocket.send!"))

        # Accept the connection
        self.factory.dispatch_reply(message['reply_channel'], {'accept': True})

        # Make sure that we get a 101 Switching Protocols back
        response = self.tr.value()
        self.assertIn(b"HTTP/1.1 101 Switching Protocols\r\n", response)
        self.assertIn(
            b"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\n",
            response)
        self.tr.clear()

        # Send some text
        self.factory.dispatch_reply(message['reply_channel'],
                                    {'text': "Hello World!"})

        response = self.tr.value()
        self.assertEqual(response, b"\x81\x0cHello World!")
        self.tr.clear()

        # Send some bytes
        self.factory.dispatch_reply(message['reply_channel'],
                                    {'bytes': b"\xaa\xbb\xcc\xdd"})

        response = self.tr.value()
        self.assertEqual(response, b"\x82\x04\xaa\xbb\xcc\xdd")
        self.tr.clear()

        # Close the connection
        self.factory.dispatch_reply(message['reply_channel'], {'close': True})

        response = self.tr.value()
        self.assertEqual(response, b"\x88\x02\x03\xe8")
        self.tr.clear()