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")
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")
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])
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")
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])
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()