Пример #1
0
class TestHTTPResponse(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, send_channel="test!")
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.makeConnection(self.tr)

    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(["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(["http.disconnect"])
        self.assertEqual(disconnect_message['path'], "/te st-à/")
Пример #2
0
class TestProxyHandling(unittest.TestCase):
    """
    Tests that concern interaction of Daphne with proxies.

    They live in a separate test case, because they're not part of the spec.
    """

    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_x_forwarded_for_ignored(self):
        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(["http.request"])
        self.assertEqual(message['client'], ['192.168.1.1', 54321])

    def test_x_forwarded_for_parsed(self):
        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(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 80])

    def test_x_forwarded_for_port_missing(self):
        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(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 0])
Пример #3
0
def _run_through_daphne(request, channel_name):
    """
    Returns Daphne's channel message for a given request.

    This helper requires a fair bit of scaffolding and can certainly be improved,
    but it works for now.
    """
    channel_layer = ChannelLayer()
    factory = HTTPFactory(channel_layer, send_channel="test!")
    proto = factory.buildProtocol(('127.0.0.1', 0))
    transport = proto_helpers.StringTransport()
    proto.makeConnection(transport)
    proto.dataReceived(request)
    _, message = channel_layer.receive([channel_name])
    return message, factory, transport
Пример #4
0
def _run_through_daphne(request, channel_name):
    """
    Returns Daphne's channel message for a given request.

    This helper requires a fair bit of scaffolding and can certainly be improved,
    but it works for now.
    """
    channel_layer = ChannelLayer()
    factory = HTTPFactory(channel_layer, send_channel="test!")
    proto = factory.buildProtocol(('127.0.0.1', 0))
    transport = proto_helpers.StringTransport()
    proto.makeConnection(transport)
    proto.dataReceived(request)
    _, message = channel_layer.receive([channel_name])
    return message, factory, transport
Пример #5
0
class WebSocketConnection(object):
    """
    Helper class that makes it easier to test Dahpne's WebSocket support.
    """
    def __init__(self):
        self.last_message = None

        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer, send_channel="test!")
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.transport = proto_helpers.StringTransport()
        self.proto.makeConnection(self.transport)

    def receive(self, request):
        """
        Low-level method to let Daphne handle HTTP/WebSocket data
        """
        self.proto.dataReceived(request)
        _, self.last_message = self.channel_layer.receive(
            ['websocket.connect'])
        return self.last_message

    def send(self, content):
        """
        Method to respond with a channel message
        """
        if self.last_message is None:
            # Auto-connect for convenience.
            self.connect()
        self.factory.dispatch_reply(self.last_message['reply_channel'],
                                    content)
        response = self.transport.value()
        self.transport.clear()
        return response

    def connect(self, path='/', params=None, headers=None):
        """
        High-level method to perform the WebSocket handshake
        """
        request = factories.build_websocket_upgrade(path, params, headers
                                                    or [])
        message = self.receive(request)
        return message
Пример #6
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(["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(["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(["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(["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(["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(["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(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 0])
Пример #7
0
class TestWebSocketProtocol(TestCase):
    """
    Tests that the WebSocket protocol class correcly generates and parses messages.
    """
    def setUp(self):
        self.channel_layer = ChannelLayer()
        self.factory = HTTPFactory(self.channel_layer, send_channel="test!")
        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(["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("test!"))

        # 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()

    def test_connection_with_file_origin_is_accepted(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: file://\r\n"
            b"\r\n")

        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive(["websocket.connect"])
        self.assertIn((b'origin', b'file://'), message['headers'])
        self.assertTrue(message['reply_channel'].startswith("test!"))

        # 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)

    def test_connection_with_no_origin_is_accepted(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"\r\n")

        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive(["websocket.connect"])
        self.assertNotIn(
            b'origin',
            [header_tuple[0] for header_tuple in message['headers']])
        self.assertTrue(message['reply_channel'].startswith("test!"))

        # 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)
Пример #8
0
class TestWebSocketProtocol(TestCase):
    """
    Tests that the WebSocket 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(["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()

    def test_connection_with_file_origin_is_accepted(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: file://\r\n"
            b"\r\n"
        )

        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive(["websocket.connect"])
        self.assertIn((b'origin', b'file://'), message['headers'])
        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)

    def test_connection_with_no_origin_is_accepted(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"\r\n"
        )

        # Get the resulting message off of the channel layer
        _, message = self.channel_layer.receive(["websocket.connect"])
        self.assertNotIn(b'origin', [header_tuple[0] for header_tuple in message['headers']])
        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)
Пример #9
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(["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(["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(["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(["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(["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(["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(["http.request"])
        self.assertEqual(message['client'], ['10.1.2.3', 0])