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 diff --git a/graphql_ws/base.py b/graphql_ws/base.py index 9556192..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') - 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..4d7b39a 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,26 +18,28 @@ class DjangoChannelConnectionContext(BaseConnectionContext): - def __init__(self, message, request_context = None): - self.message = message + def __init__(self, send_json, close, request_context): + self.send_json = send_json + self.close = close self.operations = {} self.request_context = request_context def send(self, data): - self.message.reply_channel.send(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): - 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): @@ -53,7 +55,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 @@ -96,23 +98,17 @@ 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 receive(self, content, **kwargs): - """ - Called when a message is received with either text or bytes - filled out. - """ - self.connection_context = DjangoChannelConnectionContext(self.message) + def connect(self): + self.accept() + 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) + + def receive_json(self, content): 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):