https://github.com/graphql-python/graphql-ws
GraphQL websockets
https://github.com/graphql-python/graphql-ws
Last synced: 2 months ago
JSON representation
GraphQL websockets
- Host: GitHub
- URL: https://github.com/graphql-python/graphql-ws
- Owner: graphql-python
- License: mit
- Created: 2017-10-25T20:56:30.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2024-01-12T15:01:09.000Z (over 1 year ago)
- Last Synced: 2025-04-03T11:11:15.030Z (3 months ago)
- Language: Python
- Size: 222 KB
- Stars: 272
- Watchers: 18
- Forks: 89
- Open Issues: 26
-
Metadata Files:
- Readme: README.rst
- Changelog: HISTORY.rst
- Contributing: CONTRIBUTING.rst
- License: LICENSE
- Codeowners: CODEOWNERS
- Authors: AUTHORS.rst
Awesome Lists containing this project
README
==========
GraphQL WS
==========Websocket backend for GraphQL subscriptions.
Supports the following application servers:
Python 3 application servers, using asyncio:
* `aiohttp`_
* `websockets compatible servers`_ such as Sanic
(via `websockets `__ library)
* `Django v2+`_Python 2 application servers:
* `Gevent compatible servers`_ such as Flask
* `Django v1.x`_
(via `channels v1.x `__)Installation instructions
=========================For instaling graphql-ws, just run this command in your shell
.. code:: bash
pip install graphql-ws
Examples
========Python 3 servers
----------------Create a subscribable schema like this:
.. code:: python
import asyncio
import grapheneclass Query(graphene.ObjectType):
hello = graphene.String()@staticmethod
def resolve_hello(obj, info, **kwargs):
return "world"class Subscription(graphene.ObjectType):
count_seconds = graphene.Float(up_to=graphene.Int())async def resolve_count_seconds(root, info, up_to):
for i in range(up_to):
yield i
await asyncio.sleep(1.)
yield up_toschema = graphene.Schema(query=Query, subscription=Subscription)
aiohttp
~~~~~~~Then just plug into your aiohttp server.
.. code:: python
from graphql_ws.aiohttp import AiohttpSubscriptionServer
from .schema import schemasubscription_server = AiohttpSubscriptionServer(schema)
async def subscriptions(request):
ws = web.WebSocketResponse(protocols=('graphql-ws',))
await ws.prepare(request)await subscription_server.handle(ws)
return wsapp = web.Application()
app.router.add_get('/subscriptions', subscriptions)web.run_app(app, port=8000)
You can see a full example here:
https://github.com/graphql-python/graphql-ws/tree/master/examples/aiohttpwebsockets compatible servers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Works with any framework that uses the websockets library for its websocket
implementation. For this example, plug in your Sanic server... code:: python
from graphql_ws.websockets_lib import WsLibSubscriptionServer
from . import schemaapp = Sanic(__name__)
subscription_server = WsLibSubscriptionServer(schema)
@app.websocket('/subscriptions', subprotocols=['graphql-ws'])
async def subscriptions(request, ws):
await subscription_server.handle(ws)
return wsapp.run(host="0.0.0.0", port=8000)
Django v2+
~~~~~~~~~~Django Channels 2
~~~~~~~~~~~~~~~~~Set up with Django Channels just takes three steps:
1. Install the apps
2. Set up your schema
3. Configure the channels router applicationFirst ``pip install channels`` and it to your ``INSTALLED_APPS``. If you
want graphiQL, install the ``graphql_ws.django`` app before
``graphene_django`` to serve a graphiQL template that will work with
websockets:.. code:: python
INSTALLED_APPS = [
"channels",
"graphql_ws.django",
"graphene_django",
# ...
]Point to your schema in Django settings:
.. code:: python
GRAPHENE = {
'SCHEMA': 'yourproject.schema.schema'
}Finally, you can set up channels routing yourself (maybe using
``graphql_ws.django.routing.websocket_urlpatterns`` in your
``URLRouter``), or you can just use one of the preset channels
applications:.. code:: python
ASGI_APPLICATION = 'graphql_ws.django.routing.application'
# or
ASGI_APPLICATION = 'graphql_ws.django.routing.auth_application'Run ``./manage.py runserver`` and go to
`http://localhost:8000/graphql `__ to test!Python 2 servers
-----------------Create a subscribable schema like this:
.. code:: python
import graphene
from rx import Observableclass Query(graphene.ObjectType):
hello = graphene.String()@staticmethod
def resolve_hello(obj, info, **kwargs):
return "world"class Subscription(graphene.ObjectType):
count_seconds = graphene.Float(up_to=graphene.Int())async def resolve_count_seconds(root, info, up_to=5):
return Observable.interval(1000)\
.map(lambda i: "{0}".format(i))\
.take_while(lambda i: int(i) <= up_to)schema = graphene.Schema(query=Query, subscription=Subscription)
Gevent compatible servers
~~~~~~~~~~~~~~~~~~~~~~~~~Then just plug into your Gevent server, for example, Flask:
.. code:: python
from flask_sockets import Sockets
from graphql_ws.gevent import GeventSubscriptionServer
from schema import schemasubscription_server = GeventSubscriptionServer(schema)
app.app_protocol = lambda environ_path_info: 'graphql-ws'@sockets.route('/subscriptions')
def echo_socket(ws):
subscription_server.handle(ws)
return []You can see a full example here:
https://github.com/graphql-python/graphql-ws/tree/master/examples/flask_geventDjango v1.x
~~~~~~~~~~~For Django v1.x and Django Channels v1.x, setup your schema in ``settings.py``
.. code:: python
GRAPHENE = {
'SCHEMA': 'yourproject.schema.schema'
}Then ``pip install "channels<1"`` and it to your django apps, adding the
following to your ``settings.py``.. code:: python
CHANNELS_WS_PROTOCOLS = ["graphql-ws", ]
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "django_subscriptions.urls.channel_routing",
},
}And finally add the channel routes
.. code:: python
from channels.routing import route_class
from graphql_ws.django_channels import GraphQLSubscriptionConsumerchannel_routing = [
route_class(GraphQLSubscriptionConsumer, path=r"^/subscriptions"),
]You can see a full example here:
https://github.com/graphql-python/graphql-ws/tree/master/examples/django_subscriptions