def test_get_params_with_consumer(self): client = WSClient(ordered=True) def consumer(message): message.content['method'] = 'FAKE' message.reply_channel.send({'text': dict(AsgiRequest(message).GET)}) with apply_routes([route('websocket.receive', consumer, path=r'^/test'), route('websocket.connect', consumer, path=r'^/test')]): path = '/test?key1=val1&key2=val2&key1=val3' client.send_and_consume('websocket.connect', path=path, check_accept=False) self.assertDictEqual(client.receive(), {'key2': ['val2'], 'key1': ['val1', 'val3']}) client.send_and_consume('websocket.receive', path=path) self.assertDictEqual(client.receive(), {})
def test_list(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): for n in range(api_settings.DEFAULT_PAGE_SIZE + 1): TestModel.objects.create(name='Name-{}'.format(str(n))) json_content = self._send_and_consume('testmodel', { 'action': 'list', 'request_id': 'client-request-id', 'data': None, }) self.assertEqual(len(json_content['payload']['data']), api_settings.DEFAULT_PAGE_SIZE) json_content = self._send_and_consume('testmodel', { 'action': 'list', 'request_id': 'client-request-id', 'data': { 'page': 2 } }) self.assertEqual(len(json_content['payload']['data']), 1) self.assertEqual('client-request-id', json_content['payload']['request_id'])
def test_trigger_outbound_delete(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['username'] def group_names(self, instance, action): return ["users3"] def has_permission(self, user, action, pk): return True user = User.objects.create(username='******', email='*****@*****.**') with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users3') user.delete() received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'delete') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], 1) self.assertEqual(received['payload']['data']['username'], 'test') received = client.receive() self.assertIsNone(received)
def test_graceful_stop_when_waiting_for_main_worker(self): """ Test to stop a worker group when main worker is processing a message. SIGTERM handler shouldn't raise an exception allowing to finish processing the message and exit gracefully. """ callback, wait_running, wait_stopped = self.tracked_callback() channel_layer = self.make_channel_layer('test') Channel('test', channel_layer=channel_layer).send({'test': 'test'}, immediately=True) consumer = mock.Mock() channel_layer.router.add_route(route('test', consumer)) # Proxy `send` for counting. channel_layer.send = mock.Mock(side_effect=channel_layer.send) with test_worker_group(channel_layer, n_threads=1, callback=callback) as worker_group: wait_running() # Main worker processing msg, wait for it and exit gracefully. worker_group.sigterm_handler(None, None) wait_stopped() self.assertEqual(consumer.call_count, 1) self.assertEqual(channel_layer.send.call_count, 0)
def test_subscribe(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume('testmodel', { 'action': 'subscribe', 'data': { 'action': 'create' }, 'request_id': 'client-request-id' }) expected_response = { 'action': 'subscribe', 'request_id': 'client-request-id', 'data': {}, 'errors': [], 'response_status': 200 } self.assertEqual(json_content['payload'], expected_response) # it should be on the create group instance = TestModel.objects.create(name='test-name') expected = { 'action': 'create', 'data': TestModelSerializer(instance).data, 'model': 'tests.testmodel', 'pk': instance.id } actual = self._get_next_message() self.assertEqual(expected, actual['payload'])
def test_graceful_stop_with_multiple_threads(self): """ Test that the whole worker group is stopped gracefully on termination signal: it should finish processing current messages and exit. """ callback, wait_running, wait_stopped = self.tracked_callback() channel_layer = self.make_channel_layer('test') Channel('test', channel_layer=channel_layer).send({'test': 'test'}, immediately=True) consumer = mock.Mock() channel_layer.router.add_route(route('test', consumer)) # Proxy `send` for counting. channel_layer.send = mock.Mock(side_effect=channel_layer.send) with test_worker_group(channel_layer, n_threads=3, callback=callback) as worker_group: wait_running() # Sub-workers threads are started before main thread and most # often pick the message, so main thread is idle on termination # signal and causes raising StopWorkerGroupLoop, but that's not # always the case and sometimes main thread picks the message # and exception is not raised. try: worker_group.sigterm_handler(None, None) except StopWorkerGroupLoop: pass wait_stopped() self.assertEqual(consumer.call_count, 1) self.assertEqual(channel_layer.send.call_count, 0)
def test_inbound_delete(self): user = User.objects.create(username='******', email='*****@*****.**') class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': DELETE, 'pk': user.pk} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') self.assertIsNone(User.objects.filter(pk=user.pk).first())
def test_inbound_delete(self): user = User.objects.create(username='******', email='*****@*****.**') class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': DELETE, 'pk': user.pk} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') self.assertIsNone(User.objects.filter(pk=user.pk).first()) self.assertIsNone(client.receive())
def test_websocket_close_exception_close_code(self): def consumer(message): raise WebsocketCloseException(3001) client = WSClient(reply_channel='daphne.response.1') with apply_routes(route('websocket.receive', consumer)): client.send_and_consume('websocket.receive') self.assertEqual( client.get_next_message(client.reply_channel).content, {'close': 3001})
def test_channel_socket_exception(self): class MyChannelSocketException(ChannelSocketException): def run(self, message): message.reply_channel.send({'text': 'error'}) def consumer(message): raise MyChannelSocketException client = WSClient() with apply_routes(route('websocket.receive', consumer)): client.send_and_consume('websocket.receive') self.assertEqual(client.receive(json=False), 'error')
def test_normal_run(self): consumer = mock.Mock() Channel('test').send({'test': 'test'}, immediately=True) channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER] channel_layer.router.add_route(route('test', consumer)) old_send = channel_layer.send channel_layer.send = mock.Mock(side_effect=old_send) # proxy 'send' for counting worker = PatchedWorker(channel_layer) worker.termed = 2 worker.run() self.assertEqual(consumer.call_count, 1) self.assertEqual(channel_layer.send.call_count, 0)
def test_inbound_create(self): self.assertEqual(User.objects.all().count(), 0) class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', 'email', 'password', 'last_name'] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([ Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer) ]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': { 'action': CREATE, 'data': { 'username': '******', 'email': 'test@user_steam.com' } } }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') self.assertEqual(User.objects.all().count(), 1) user = User.objects.all().first() self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, 'test@user_steam.com') self.assertIsNone(client.receive())
def test_trigger_outbound_update(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['__all__'] @classmethod def group_names(cls, instance, action): return ["users2"] def has_permission(self, user, action, pk): return True # Make model and clear out pending sends user = User.objects.create(username='******', email='*****@*****.**') consumer_finished.send(sender=None) with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users2') user.username = '******' user.save() consumer_finished.send(sender=None) received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('last_name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'update') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test_new') self.assertEqual(received['payload']['data']['password'], '') self.assertEqual(received['payload']['data']['last_name'], '') received = client.receive() self.assertIsNone(received)
def test_retrieve_404(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume('testmodel', { 'action': 'retrieve', 'pk': 1, 'request_id': 'client-request-id' }) expected = { 'action': 'retrieve', 'data': None, 'errors': ['Not found.'], 'response_status': 404, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected)
def test_ordering(self): client = WSClient(ordered=True) @enforce_ordering def consumer(message): message.reply_channel.send({'text': message['text']}) with apply_routes(route('websocket.receive', consumer)): client.send_and_consume('websocket.receive', text='1') # order = 0 client.send_and_consume('websocket.receive', text='2') # order = 1 client.send_and_consume('websocket.receive', text='3') # order = 2 self.assertEqual(client.receive(), 1) self.assertEqual(client.receive(), 2) self.assertEqual(client.receive(), 3)
def test_inbound_update(self): user = User.objects.create(username='******', email='*****@*****.**') class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', ] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'username': '******'}} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') user = User.objects.get(pk=user.pk) self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, '*****@*****.**') # trying change field that not in binding fields client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'email': '*****@*****.**'}} }) client.consume('binding.users') user = User.objects.get(pk=user.pk) self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, '*****@*****.**')
def test_retrieve(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): instance = TestModel.objects.create(name="Test") json_content = self._send_and_consume('testmodel', { 'action': 'retrieve', 'pk': instance.id, 'request_id': 'client-request-id' }) expected = { 'action': 'retrieve', 'data': TestModelSerializer(instance).data, 'errors': [], 'response_status': 200, 'request_id': 'client-request-id' } self.assertTrue(json_content['payload'] == expected)
def start(self): rows_affected = self._acquire() if rows_affected == 0: return if rows_affected != 1: raise Exception() try: from channels.asgi import channel_layers from channels import route from channels import DEFAULT_CHANNEL_LAYER channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER] if self.mqtt_client is None: channel_layer.router.add_route( route(self.channel, self.consumer)) self.mqtt_client = self.make_client() self.mqtt_client.loop_start() except: self._release()
def test_trigger_outbound_create_exclude(self): class TestBinding(WebsocketBinding): model = User stream = 'test' exclude = ['first_name', 'last_name'] @classmethod def group_names(cls, instance): return ["users_exclude"] def has_permission(self, user, action, pk): return True with apply_routes([route('test', TestBinding.consumer)]): client = HttpClient() client.join_group('users_exclude') user = User.objects.create(username='******', email='*****@*****.**') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertFalse('last_name' in received['payload']['data']) self.assertFalse('first_name' in received['payload']['data']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test') self.assertEqual(received['payload']['data']['password'], '') received = client.receive() self.assertIsNone(received)
def test_subscribe_failure(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume('testmodel', { 'action': 'subscribe', 'data': { }, 'request_id': 'client-request-id' }) expected = { 'action': 'subscribe', 'data': None, 'errors': ['action required'], 'request_id': 'client-request-id', 'response_status': 400 } self.assertEqual(expected, json_content['payload'])
def test_trigger_outbound_create_exclude(self): class TestBinding(WebsocketBinding): model = User stream = 'test' exclude = ['first_name', 'last_name'] @classmethod def group_names(cls, instance): return ["users_exclude"] def has_permission(self, user, action, pk): return True with apply_routes([route('test', TestBinding.consumer)]): client = WSClient() client.join_group('users_exclude') user = User.objects.create(username='******', email='*****@*****.**') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertFalse('last_name' in received['payload']['data']) self.assertFalse('first_name' in received['payload']['data']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test') self.assertEqual(received['payload']['data']['password'], '') received = client.receive() self.assertIsNone(received)
def test_update_failure(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume('testmodel', { 'action': 'update', 'pk': -1, 'data': {'name': 'some-value'}, 'request_id': 'client-request-id' }) expected = { 'data': None, 'action': 'update', 'errors': ['Not found.'], 'response_status': 404, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected)
def test_run_with_consume_later_error(self): # consumer with ConsumeLater error at first call def _consumer(message, **kwargs): _consumer._call_count = getattr(_consumer, '_call_count', 0) + 1 if _consumer._call_count == 1: raise ConsumeLater() Channel('test').send({'test': 'test'}, immediately=True) channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER] channel_layer.router.add_route(route('test', _consumer)) old_send = channel_layer.send channel_layer.send = mock.Mock(side_effect=old_send) # proxy 'send' for counting worker = PatchedWorker(channel_layer) worker.termed = 2 # first loop with error, second with sending worker.run() self.assertEqual(getattr(_consumer, '_call_count', None), 2) self.assertEqual(channel_layer.send.call_count, 1)
def test_delete(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): instance = TestModel.objects.create(name='test-name') json_content = self._send_and_consume('testmodel', { 'action': 'delete', 'pk': instance.id, 'request_id': 'client-request-id', }) expected = { 'action': 'delete', 'errors': [], 'data': {}, 'request_id': 'client-request-id', 'response_status': 200 } self.assertEqual(json_content['payload'], expected) self.assertEqual(TestModel.objects.count(), 0)
def test_update(self): with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): instance = TestModel.objects.create(name='some-test') json_content = self._send_and_consume('testmodel', { 'action': 'update', 'pk': instance.id, 'data': {'name': 'some-value'}, 'request_id': 'client-request-id' }) instance.refresh_from_db() expected = { 'action': 'update', 'errors': [], 'data': TestModelSerializer(instance).data, 'response_status': 200, 'request_id': 'client-request-id' } self.assertEqual(json_content['payload'], expected)
def test_create_failure(self): """Integration that asserts error handling of a message to the create channel.""" with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume('testmodel', { 'action': 'create', 'pk': None, 'request_id': 'client-request-id', 'data': {}, }) # it should not create an object self.assertEqual(TestModel.objects.count(), 0) expected = { 'action': 'create', 'data': None, 'request_id': 'client-request-id', 'errors': [{'name': ['This field is required.']}], 'response_status': 400 } # it should respond with an error self.assertEqual(json_content['payload'], expected)
def test_inbound_create(self): self.assertEqual(User.objects.all().count(), 0) class Demultiplexer(WebsocketDemultiplexer): mapping = { 'users': 'binding.users', } groups = ['inbound'] class UserBinding(WebsocketBinding): model = User stream = 'users' fields = ['username', 'email', 'password', 'last_name'] @classmethod def group_names(cls, instance, action): return ['users_outbound'] def has_permission(self, user, action, pk): return True with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]): client = HttpClient() client.send_and_consume('websocket.connect', path='/') client.send_and_consume('websocket.receive', path='/', text={ 'stream': 'users', 'payload': {'action': CREATE, 'data': {'username': '******', 'email': 'test@user_steam.com'}} }) # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer client.consume('binding.users') self.assertEqual(User.objects.all().count(), 1) user = User.objects.all().first() self.assertEqual(user.username, 'test_inbound') self.assertEqual(user.email, 'test@user_steam.com') self.assertIsNone(client.receive())
def test_create(self): """Integration that asserts routing a message to the create channel. Asserts response is correct and an object is created. """ with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]): json_content = self._send_and_consume(TestModelResourceBinding.stream, { 'action': 'create', 'pk': None, 'request_id': 'client-request-id', 'data': {'name': 'some-thing'}}) # it should create an object self.assertEqual(TestModel.objects.count(), 1) expected = { 'action': 'create', 'data': TestModelSerializer(TestModel.objects.first()).data, 'errors': [], 'request_id': 'client-request-id', 'response_status': 201 } # it should respond with the serializer.data self.assertEqual(json_content['payload'], expected)
from channels import route, route_class from channels.generic.websockets import WebsocketDemultiplexer from posts.bindings import LiveblogResource class APIDemultiplexer(WebsocketDemultiplexer): mapping = { 'liveblogs': 'liveblogs' } # The channel routing defines what channels get handled by what consumers, # including optional matching on message attributes. WebSocket messages of all # types have a 'path' attribute, so we're using that to route the socket. # While this is under stream/ compared to the HTML page, we could have it on the # same URL if we wanted; Daphne separates by protocol as it negotiates with a browser. channel_routing = [ route_class(APIDemultiplexer), route("liveblogs", LiveblogResource.consumer) # A default "http.request" route is always inserted by Django at the end of the routing list # that routes all unmatched HTTP requests to the Django view system. If you want lower-level # HTTP handling - e.g. long-polling - you can do it here and route by path, and let the rest # fall through to normal views. ]
from channels import route from jobs import consumers channel_routing = [ # Wire up websocket channels to our consumers: route("websocket.connect", consumers.ws_connect), route("websocket.receive", consumers.ws_receive), ]
from channels import route, route_class from blocks.consumers.block import parse_block, repair_block, check_block_hash from blocks.consumers.transaction import repair_transaction from blocks.consumers.address import parse_address from blocks.consumers.info import display_info from blocks.consumers.websockets import ws_connect, ws_disconnect, ws_receive from blocks.consumers.angular_consumers.demultiplexers import BlockDemultiplexer, LatestBlocksDemultiplexer channel_routing = [ # Blocks route('parse_block', parse_block), route('repair_block', repair_block), route('check_block_hash', check_block_hash), # Transactions route('repair_transaction', repair_transaction), # Addresses route('parse_address', parse_address), # Info route('display_info', display_info), # Demultiplexing route_class(BlockDemultiplexer, path="^/block/$"), route_class(LatestBlocksDemultiplexer, path="^/latest_blocks/$"), # Websockets route('websocket.connect', ws_connect), route('websocket.disconnect', ws_disconnect), route('websocket.receive', ws_receive),
from . import consumers from channels import route channel_routing = [ route('websocket.connect', consumers.ws_connect), route('websocket.receive', consumers.ws_receive), route('websocket.disconnect', consumers.ws_disconnect), ]
from channels import route from .consumers import ws_connect, ws_receive, ws_disconnect, chat_join, chat_leave, chat_send # There's no path matching on these routes; we just rely on the matching # from the top-level routing. We _could_ path match here if we wanted. websocket_routing = [ # Called when WebSockets connect route("websocket.connect", ws_connect), # Called when WebSockets get sent a data frame route("websocket.receive", ws_receive), # Called when WebSockets disconnect route("websocket.disconnect", ws_disconnect), ] # You can have as many lists here as you like, and choose any name. # Just refer to the individual names in the include() function. custom_routing = [ # Handling different chatt commands (websocket.receive is decoded and put # onto this channel) - routed on the "command" attribute of the decoded # message. route("chatt.receive", chat_join, command="^join$"), route("chatt.receive", chat_leave, command="^leave$"), route("chatt.receive", chat_send, command="^send$"), ]
from channels import route from blocks.consumers.info import display_info from blocks.consumers.websockets import ws_connect, ws_disconnect, ws_receive channel_routing = [ # Info route("display_info", display_info), # Websockets route("websocket.connect", ws_connect), route("websocket.disconnect", ws_disconnect), route("websocket.receive", ws_receive), ]
from channels import route from .consumers import (ws_connect_api, ws_receive_api, ws_disconnect_api, chat_send_api, bot_send_api) # There's no path matching on these routes; we just rely on the matching # from the top-level routing. We _could_ path match here if we wanted. websocket_routing = [ # Called when WebSockets connect route("websocket.connect", ws_connect_api), # Called when WebSockets get sent a data frame route("websocket.receive", ws_receive_api), # Called when WebSockets disconnect route("websocket.disconnect", ws_disconnect_api), ] # You can have as many lists here as you like, and choose any name. # Just refer to the individual names in the include() function. custom_routing = [ # Handling different chat commands (websocket.receive is decoded and put # onto this channel) - routed on the "command" attribute of the decoded # message. # route("chat.receive", chat_join, command="^join$"), # route("chat.receive", chat_leave, command="^leave$"), # route("chat.receive", chat_send, command="^send$"), route("chat-api.receive", chat_send_api, command="^send$"), route("bot-api.receive", bot_send_api), ]
from channels.staticfiles import StaticFilesConsumer from channels import route from login import consumers channel_routing = [ # This makes Django serve static files from settings.STATIC_URL, similar # to django.views.static.serve. This isn't ideal (not exactly production # quality) but it works for a minimal example. route('http.request', StaticFilesConsumer()), # Wire up websocket channels to our consumers: route('websocket.connect', consumers.connect_to_nifty_channel, path = r'^/nifty-channel/' ), route('websocket.disconnect', consumers.disconnect_from_nifty_channel, path = r'^/nifty-channel/', ), route('websocket.connect', consumers.connect_to_leaderboard_channel, path = r'^/leaderboard-channel/' ),
from channels import route from dashboard import consumers channel_routing = [ route('websocket.connect', consumers.ws_connect), route('websocket.receive', consumers.ws_receive), route('websocket.disconnect', consumers.ws_disconnect), ]
from channels import route from .consumers import ws_connect, ws_receive, ws_disconnect, handle_chat_message # There's no path matching on these routes; we just rely on the matching # from the top-level routing. We _could_ path match here if we wanted. websocket_routing = [ # Called when WebSockets connect route("websocket.connect", ws_connect), # Called when WebSockets get sent a data frame route("websocket.receive", ws_receive), # Called when WebSockets disconnect route("websocket.disconnect", ws_disconnect), ] # You can have as many lists here as you like, and choose any name. # Just refer to the individual names in the include() function. custom_routing = [ # Custom channel route("chat_messages", handle_chat_message), ]
from channels import route from .consumers import * message_routing = [ route("websocket.connect", ws_connect), route("websocket.disconnect", ws_disconnect), route("websocket.receive", ws_receive), ]
Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from channels import route from django.conf.urls import include, url from django.contrib import admin from app.views import IndexView from channels_example.app.consumers import ws_message, ws_add, ws_disconnect urlpatterns = [ url(r'^$', IndexView.as_view()), url(r'^admin/', include(admin.site.urls)), url(r'^accounts/', include('django.contrib.auth.urls')), ] channel_routing = [ route("websocket.receive", ws_message), route("websocket.connect", ws_add), route("websocket.disconnect", ws_disconnect), ]
from channels import route from .consumers import (ws_connect, ws_disconnect, ws_message, chat_receive, friends_added, friend_delete, films_added_for_voting, film_delete, voting, settings_changed) # There's no path matching on these routes; we just rely on the matching # from the top-level routing. We could path match here if we wanted. websocket_routing = [ route("websocket.connect", ws_connect), route("websocket.receive", ws_message), route("websocket.disconnect", ws_disconnect) ] room_routing = [ route("room.receive", chat_receive, command="^chat$"), route("room.receive", friends_added, command="^add_friends$"), route("room.receive", friend_delete, command="^delete_friend"), route("room.receive", films_added_for_voting, command="^add_film_voting"), route("room.receive", film_delete, command="^delete_film_voting"), route("room.receive", voting, command="^voting"), route("room.receive", settings_changed, command="^settings"), ]
from channels import route # This function will display all messages received in the console def message_handler(message): print(message['text']) channel_routing = [ route("websocket.receive", message_handler) # we register our message handler ] from channels import include # The channel routing defines what channels get handled by what consumers, # including optional matching on message attributes. In this example, we match # on a path prefix, and then include routing from the chat module. channel_routing = [ # Include sub-routing from an app. include("chat.routing.websocket_routing", path=r"^/chat/stream"), # Custom handler for message sending (see Room.send_message). # Can't go in the include above as it's not got a 'path' attribute to match on. include("chat.routing.custom_routing"), # A default "http.request" route is always inserted by Django at the end of the routing list # that routes all unmatched HTTP requests to the Django view system. If you want lower-level # HTTP handling - e.g. long-polling - you can do it here and route by path, and let the rest # fall through to normal views. ]
# -*- coding: utf-8 -*- from __future__ import absolute_import, print_function, unicode_literals from channels import route from .consumers import liveblog_connect, liveblog_disconnect channel_routing = [ route( 'websocket.connect', liveblog_connect, path=r'^/liveblog/(?P<apphook>[a-zA-Z0-9_-]+)/' r'(?P<lang>[a-zA-Z_-]+)/(?P<post>[a-zA-Z0-9_-]+)/$' ), route( 'websocket.disconnect', liveblog_disconnect, path=r'^/liveblog/(?P<apphook>[a-zA-Z0-9_-]+)/' r'(?P<lang>[a-zA-Z_-]+)/(?P<post>[a-zA-Z0-9_-]+)/$' ), ]
from channels import include, route from api.views.web_socket import ChatSocketView, CompositionSocketView composition_routing = [ route("websocket.connect", "api.consumers.base.pass_message"), route("websocket.receive", CompositionSocketView.as_view()), route("websocket.disconnect", CompositionSocketView.as_view()), ] chat_routing = [ route("websocket.connect", "api.consumers.base.pass_message"), route("websocket.receive", ChatSocketView.as_view()), route("websocket.disconnect", ChatSocketView.as_view()), ] not_found_routing = [ route("websocket.connect", "api.consumers.base.pass_message"), route("websocket.receive", "api.consumers.base.pass_message"), route("websocket.disconnect", "api.consumers.base.pass_message"), ] main_routing = [ # TODO поправить в настройках nginx include(composition_routing, path=r"^/ws/composition/(?P<composition_id>\d+)/$"), include(chat_routing, path=r"^/ws/chat/(?P<band_id>\d+)/$"), include(not_found_routing), ]
from channels import route from posts.consumers import connect_blog, disconnect_blog from livetweets.consumers import connect_tweeter, disconnect_tweeter # The channels routing defines what the channels get handled by what consumers, # including optional matching on message attributes. Websocket messages of all # types have a 'path' attribute, so we're using that to route the socket. # While this is under stream/ compared to the HTML page, we could have it on the # same URL if we wanted; Daphne separates by protocol as it negotiates with a browser channel_routing = [ # called when incoming Websockets connect route('websocket.connect', connect_blog, path=r'/liveblog/(?P<slug>[^/]+)/stream/$'), # called when the client closes the socket route('websocket.disconnet', disconnect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$'), # called when incoming Websockets connect route('websocket.connect', connect_tweeter, path=r'/livetweets/stream/$'), # called when the client closes the socket route('websocket.disconnet', disconnect_tweeter, path=r'^/livetweets/stream/$'), ]
from channels import route from channels.staticfiles import StaticFilesConsumer from posts.consumers import connect_blog, disconnect_blog, http_consumer # The channel routing defines what channels get handled by what consumers, # including optional matching on message attributes. WebSocket messages of all # types have a 'path' attribute, so we're using that to route the socket. # While this is under stream/ compared to the HTML page, we could have it on the # same URL if we wanted; Daphne separates by protocol as it negotiates with a browser. channel_routing = [ # Called when incoming WebSockets connect route("websocket.connect", connect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$'), # Called when the client closes the socket route("websocket.disconnect", disconnect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$'), route("http.request", StaticFilesConsumer()), # A default "http.request" route is always inserted by Django at the end of the routing list # that routes all unmatched HTTP requests to the Django view system. If you want lower-level # HTTP handling - e.g. long-polling - you can do it here and route by path, and let the rest # fall through to normal views. ]
from channels.staticfiles import StaticFilesConsumer from channels import route from . import consumers channel_routing = [ # This makes Django serve static files from settings.STATIC_URL, similar # to django.views.static.serve. This isn't ideal (not exactly production # quality) but it works for a minimal example. route('http.request', StaticFilesConsumer()), # Wire up websocket channels to our consumers: route('websocket.connect', consumers.connect_to_nifty_channel, path=r'^/nifty-channel/'), route( 'websocket.disconnect', consumers.disconnect_from_nifty_channel, path=r'^/nifty-channel/', ), route('websocket.connect', consumers.connect_to_leaderboard_channel, path=r'^/leaderboard-channel/'), route( 'websocket.disconnect', consumers.disconnect_from_leaderboard_channel, path=r'^/leaderboard-channel/', ), route('websocket.connect', consumers.connect_to_ticker_channel, path=r'^/ticker-channel/'), route(
from channels import route # This function will display all messages received in the console def message_handler(message): print(message['text']) channel_routing = [ route("websocket.receive", message_handler) # we register our message handler ]
from channels import route, route_class from .consumers import ChatServer, events, Demultiplexer, RoomBinding chat_routing = [ route_class(ChatServer, path=r'^(?P<slug>[^/]+)/stream/$'), ] event_routing = [ route('chat.receive', events.user_join, event=r'^user-join$'), route('chat.receive', events.user_leave, event=r'^user-leave$'), route('chat.receive', events.client_send, event=r'^message-send$'), ] binding_routing = [ route_class(Demultiplexer, path=r'^/binding/'), route('binding.room', RoomBinding.consumer), ]
from channels import route_class, route from values.consumers import Demultiplexer from values.models import IntegerValueBinding # The channel routing defines what channels get handled by what consumers, # including optional matching on message attributes. In this example, we route # all WebSocket connections to the class-based BindingConsumer (the consumer # class itself specifies what channels it wants to consume) channel_routing = [ route_class(Demultiplexer, path='^/stream/?$'), route("binding.intval", IntegerValueBinding.consumer), ]
from channels import route from .consumers import ( ws_connect, ws_receive, ws_disconnect, votes_update ) websocket_routing = [ route('websocket.connect', ws_connect), route('websocket.receive', ws_receive), route('websocket.disconnect', ws_disconnect), ] votes_routing = [ route('votes.receive', votes_update, command='^update$'), ]
# coding=utf-8 from __future__ import unicode_literals from channels import include, route from chat.views import ChatWebSocketView, DRFChatWebSocketView routing = [ route('websocket.connect', ChatWebSocketView.as_view(), path=r'^default/'), # include(DRFChatWebSocketView.as_view(), path=r'^drf/'), ]