From baf6abdab516f89337777264045efe11d92337e9 Mon Sep 17 00:00:00 2001 From: colan connon Date: Mon, 19 Feb 2018 16:04:09 -0500 Subject: [PATCH 1/5] started on channels 2 updates --- .../django_subscriptions/asgi.py | 10 ++++---- .../django_subscriptions/routing.py | 18 ++++++++++++++ .../django_subscriptions/settings.py | 24 +++++++++++-------- .../django_subscriptions/template.py | 2 +- .../django_subscriptions/urls.py | 5 ---- 5 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 examples/django_subscriptions/django_subscriptions/routing.py diff --git a/examples/django_subscriptions/django_subscriptions/asgi.py b/examples/django_subscriptions/django_subscriptions/asgi.py index e6edd7d..579ff6e 100644 --- a/examples/django_subscriptions/django_subscriptions/asgi.py +++ b/examples/django_subscriptions/django_subscriptions/asgi.py @@ -1,6 +1,8 @@ -import os -from channels.asgi import get_channel_layer -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_subscriptions.settings") +import os +import django +from channels.routing import get_default_application -channel_layer = get_channel_layer() \ No newline at end of file +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "multichat.settings") +django.setup() +application = get_default_application() \ No newline at end of file diff --git a/examples/django_subscriptions/django_subscriptions/routing.py b/examples/django_subscriptions/django_subscriptions/routing.py new file mode 100644 index 0000000..501a67f --- /dev/null +++ b/examples/django_subscriptions/django_subscriptions/routing.py @@ -0,0 +1,18 @@ +from graphql_ws.django_channels import GraphQLSubscriptionConsumer +from django.urls import path + +from channels.http import AsgiHandler +from channels.routing import ProtocolTypeRouter, URLRouter +from channels.auth import AuthMiddlewareStack +import logging + +logger = logging.getLogger('django') + + +application = ProtocolTypeRouter({ + "websocket": AuthMiddlewareStack( + URLRouter([ + path("subscriptions", GraphQLSubscriptionConsumer), + ]) + ), +}) \ No newline at end of file diff --git a/examples/django_subscriptions/django_subscriptions/settings.py b/examples/django_subscriptions/django_subscriptions/settings.py index 45d0471..90b4470 100644 --- a/examples/django_subscriptions/django_subscriptions/settings.py +++ b/examples/django_subscriptions/django_subscriptions/settings.py @@ -27,6 +27,7 @@ ALLOWED_HOSTS = [] +ASGI_APPLICATION = "django_subscriptions.routing.application" # Application definition @@ -40,6 +41,7 @@ 'channels', ] + MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -119,19 +121,21 @@ # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' -CHANNELS_WS_PROTOCOLS = ["graphql-ws", ] -CHANNEL_LAYERS = { - "default": { - "BACKEND": "asgi_redis.RedisChannelLayer", - "CONFIG": { - "hosts": [("localhost", 6379)], - }, - "ROUTING": "django_subscriptions.urls.channel_routing", - }, +CHANNELS_WS_PROTOCOLS = ["graphql-ws"] + -} GRAPHENE = { 'SCHEMA': 'django_subscriptions.schema.schema' +} + +LOGGING = { + 'version': 1, + 'handlers': { + 'console': { + 'level': 'INFO', + 'class': 'logging.StreamHandler', + } + } } \ No newline at end of file diff --git a/examples/django_subscriptions/django_subscriptions/template.py b/examples/django_subscriptions/django_subscriptions/template.py index b067ae5..06c77f1 100644 --- a/examples/django_subscriptions/django_subscriptions/template.py +++ b/examples/django_subscriptions/django_subscriptions/template.py @@ -119,7 +119,7 @@ def render_graphiql(): ''').substitute( GRAPHIQL_VERSION='0.11.10', SUBSCRIPTIONS_TRANSPORT_VERSION='0.7.0', - subscriptionsEndpoint='ws://localhost:8000/subscriptions', + subscriptionsEndpoint='ws://127.0.0.1:8000/subscriptions', # subscriptionsEndpoint='ws://localhost:5000/', endpointURL='/graphql', ) diff --git a/examples/django_subscriptions/django_subscriptions/urls.py b/examples/django_subscriptions/django_subscriptions/urls.py index 3848d22..0e4824b 100644 --- a/examples/django_subscriptions/django_subscriptions/urls.py +++ b/examples/django_subscriptions/django_subscriptions/urls.py @@ -32,9 +32,4 @@ def graphiql(request): url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))) ] -from channels.routing import route_class -from graphql_ws.django_channels import GraphQLSubscriptionConsumer -channel_routing = [ - route_class(GraphQLSubscriptionConsumer, path=r"^/subscriptions"), -] \ No newline at end of file From 9fc5a3068333774b4bf043c9f1a95c263dee0b3e Mon Sep 17 00:00:00 2001 From: colan connon Date: Mon, 19 Feb 2018 16:09:30 -0500 Subject: [PATCH 2/5] stage rest of changes --- graphql_ws/base.py | 2 +- graphql_ws/django_channels.py | 39 +++++++++++++++-------------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/graphql_ws/base.py b/graphql_ws/base.py index 9556192..4d71c74 100644 --- a/graphql_ws/base.py +++ b/graphql_ws/base.py @@ -80,7 +80,7 @@ def process_message(self, connection_context, parsed_message): op_id = parsed_message.get('id') op_type = parsed_message.get('type') payload = parsed_message.get('payload') - + print(op_type) if op_type == GQL_CONNECTION_INIT: return self.on_connection_init(connection_context, op_id, payload) diff --git a/graphql_ws/django_channels.py b/graphql_ws/django_channels.py index 5b75629..50fed01 100644 --- a/graphql_ws/django_channels.py +++ b/graphql_ws/django_channels.py @@ -1,4 +1,4 @@ -from channels.generic.websockets import JsonWebsocketConsumer +from channels.generic.websocket import JsonWebsocketConsumer from .base import BaseConnectionContext import json from graphql.execution.executors.sync import SyncExecutor @@ -18,20 +18,18 @@ class DjangoChannelConnectionContext(BaseConnectionContext): - def __init__(self, message, request_context = None): - self.message = message + def __init__(self, send_json, close, request_context=None): + self.send_json = send_json + self.close = close self.operations = {} - self.request_context = request_context + self.request_context = None def send(self, data): - self.message.reply_channel.send(data) + print(data) + self.send_json(data) def close(self, reason): - data = { - 'close': True, - 'text': reason - } - self.message.reply_channel.send(data) + self.close() class DjangoChannelSubscriptionServer(BaseSubscriptionServer): @@ -53,7 +51,7 @@ def send_message(self, connection_context, op_id=None, op_type=None, payload=Non message['payload'] = payload assert message, "You need to send at least one thing" - return connection_context.send({'text': json.dumps(message)}) + return connection_context.send(message) def on_open(self, connection_context): pass @@ -67,6 +65,7 @@ def on_connection_init(self, connection_context, op_id, payload): self.send_message(connection_context, op_type=GQL_CONNECTION_ACK) except Exception as e: + print(e) self.send_error(connection_context, op_id, e, GQL_CONNECTION_ERROR) connection_context.close(1011) @@ -96,23 +95,19 @@ def on_stop(self, connection_context, op_id): class GraphQLSubscriptionConsumer(JsonWebsocketConsumer): - http_user_and_session = True - strict_ordering = True - def connect(self, message, **kwargs): - message.reply_channel.send({"accept": True}) + def connect(self): + print('here') + self.accept() - - def receive(self, content, **kwargs): - """ - Called when a message is received with either text or bytes - filled out. - """ - self.connection_context = DjangoChannelConnectionContext(self.message) + def receive_json(self, content): + print(content) + self.connection_context = DjangoChannelConnectionContext(self.send_json, self.close) self.subscription_server = DjangoChannelSubscriptionServer(graphene_settings.SCHEMA) self.subscription_server.on_open(self.connection_context) self.subscription_server.handle(content, self.connection_context) + class SubscriptionObserver(Observer): def __init__(self, connection_context, op_id, send_execution_result, send_error, on_close): From 5b152b39aa4c21142a1fdb67421eb60535e85b14 Mon Sep 17 00:00:00 2001 From: colan connon Date: Mon, 19 Feb 2018 16:10:18 -0500 Subject: [PATCH 3/5] remove print statements --- graphql_ws/django_channels.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/graphql_ws/django_channels.py b/graphql_ws/django_channels.py index 50fed01..23493b9 100644 --- a/graphql_ws/django_channels.py +++ b/graphql_ws/django_channels.py @@ -25,7 +25,6 @@ def __init__(self, send_json, close, request_context=None): self.request_context = None def send(self, data): - print(data) self.send_json(data) def close(self, reason): @@ -65,7 +64,6 @@ def on_connection_init(self, connection_context, op_id, payload): self.send_message(connection_context, op_type=GQL_CONNECTION_ACK) except Exception as e: - print(e) self.send_error(connection_context, op_id, e, GQL_CONNECTION_ERROR) connection_context.close(1011) @@ -97,11 +95,9 @@ def on_stop(self, connection_context, op_id): class GraphQLSubscriptionConsumer(JsonWebsocketConsumer): def connect(self): - print('here') self.accept() def receive_json(self, content): - print(content) self.connection_context = DjangoChannelConnectionContext(self.send_json, self.close) self.subscription_server = DjangoChannelSubscriptionServer(graphene_settings.SCHEMA) self.subscription_server.on_open(self.connection_context) From efabfc4623bb02c9fe28a18a891544bed417c539 Mon Sep 17 00:00:00 2001 From: colan connon Date: Mon, 19 Feb 2018 19:49:53 -0500 Subject: [PATCH 4/5] refactor the order to make moe sense --- graphql_ws/django_channels.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphql_ws/django_channels.py b/graphql_ws/django_channels.py index 23493b9..75f2b67 100644 --- a/graphql_ws/django_channels.py +++ b/graphql_ws/django_channels.py @@ -96,11 +96,11 @@ class GraphQLSubscriptionConsumer(JsonWebsocketConsumer): def connect(self): self.accept() - - def receive_json(self, content): self.connection_context = DjangoChannelConnectionContext(self.send_json, self.close) self.subscription_server = DjangoChannelSubscriptionServer(graphene_settings.SCHEMA) self.subscription_server.on_open(self.connection_context) + + def receive_json(self, content): self.subscription_server.handle(content, self.connection_context) From 01364810d389f46eea3ec67c5f6235d76fe334aa Mon Sep 17 00:00:00 2001 From: colan connon Date: Tue, 20 Feb 2018 07:58:09 -0500 Subject: [PATCH 5/5] context now works --- graphql_ws/base.py | 1 - graphql_ws/django_channels.py | 17 +++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/graphql_ws/base.py b/graphql_ws/base.py index 4d71c74..2a13c81 100644 --- a/graphql_ws/base.py +++ b/graphql_ws/base.py @@ -80,7 +80,6 @@ def process_message(self, connection_context, parsed_message): op_id = parsed_message.get('id') op_type = parsed_message.get('type') payload = parsed_message.get('payload') - print(op_type) if op_type == GQL_CONNECTION_INIT: return self.on_connection_init(connection_context, op_id, payload) diff --git a/graphql_ws/django_channels.py b/graphql_ws/django_channels.py index 75f2b67..4d7b39a 100644 --- a/graphql_ws/django_channels.py +++ b/graphql_ws/django_channels.py @@ -18,11 +18,11 @@ class DjangoChannelConnectionContext(BaseConnectionContext): - def __init__(self, send_json, close, request_context=None): + def __init__(self, send_json, close, request_context): self.send_json = send_json self.close = close self.operations = {} - self.request_context = None + self.request_context = request_context def send(self, data): self.send_json(data) @@ -32,9 +32,14 @@ def close(self, reason): class DjangoChannelSubscriptionServer(BaseSubscriptionServer): - def get_graphql_params(self, *args, **kwargs): - params = super(DjangoChannelSubscriptionServer, - self).get_graphql_params(*args, **kwargs) + def get_graphql_params(self, connection_context, payload): + params = { + 'request_string': payload.get('query'), + 'variable_values': payload.get('variables'), + 'operation_name': payload.get('operationName'), + 'context_value': connection_context.request_context, + } + return dict(params, executor=SyncExecutor()) def handle(self, message, connection_context): @@ -96,7 +101,7 @@ class GraphQLSubscriptionConsumer(JsonWebsocketConsumer): def connect(self): self.accept() - self.connection_context = DjangoChannelConnectionContext(self.send_json, self.close) + self.connection_context = DjangoChannelConnectionContext(self.send_json, self.close, self.scope) self.subscription_server = DjangoChannelSubscriptionServer(graphene_settings.SCHEMA) self.subscription_server.on_open(self.connection_context)