Skip to content

Commit feea531

Browse files
authored
Implementation of graphql-ws protocol (#242)
* Supporting both apollo and graphql-ws protocol in same class
1 parent 7992721 commit feea531

11 files changed

+1462
-24
lines changed

docs/modules/transport.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ gql.transport
1414
.. autoclass:: gql.transport.aiohttp.AIOHTTPTransport
1515

1616
.. autoclass:: gql.transport.websockets.WebsocketsTransport
17+
18+
.. autoclass:: gql.transport.phoenix_channel_websockets.PhoenixChannelWebsocketsTransport

docs/transports/aiohttp.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ AIOHTTPTransport
55

66
This transport uses the `aiohttp`_ library and allows you to send GraphQL queries using the HTTP protocol.
77

8+
Reference: :py:class:`gql.transport.aiohttp.AIOHTTPTransport`
9+
810
.. note::
911

1012
GraphQL subscriptions are not supported on the HTTP transport.

docs/transports/requests.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ RequestsHTTPTransport
66
The RequestsHTTPTransport is a sync transport using the `requests`_ library
77
and allows you to send GraphQL queries using the HTTP protocol.
88

9+
Reference: :py:class:`gql.transport.requests.RequestsHTTPTransport`
10+
911
.. literalinclude:: ../code_examples/requests_sync.py
1012

1113
.. _requests: https://requests.readthedocs.io

docs/transports/websockets.rst

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,29 @@
33
WebsocketsTransport
44
===================
55

6-
The websockets transport implements the `Apollo websockets transport protocol`_.
6+
The websockets transport supports both:
7+
8+
- the `Apollo websockets transport protocol`_.
9+
- the `GraphQL-ws websockets transport protocol`_
10+
11+
It will detect the backend supported protocol from the response http headers returned.
712

813
This transport allows to do multiple queries, mutations and subscriptions on the same websocket connection.
914

15+
Reference: :py:class:`gql.transport.websockets.WebsocketsTransport`
16+
1017
.. literalinclude:: ../code_examples/websockets_async.py
1118

1219
Websockets SSL
1320
--------------
1421

1522
If you need to connect to an ssl encrypted endpoint:
1623

17-
* use _wss_ instead of _ws_ in the url of the transport
24+
* use :code:`wss` instead of :code:`ws` in the url of the transport
1825

1926
.. code-block:: python
2027
21-
sample_transport = WebsocketsTransport(
28+
transport = WebsocketsTransport(
2229
url='wss://SERVER_URL:SERVER_PORT/graphql',
2330
headers={'Authorization': 'token'}
2431
)
@@ -34,7 +41,7 @@ If you have a self-signed ssl certificate, you need to provide an ssl_context wi
3441
localhost_pem = pathlib.Path(__file__).with_name("YOUR_SERVER_PUBLIC_CERTIFICATE.pem")
3542
ssl_context.load_verify_locations(localhost_pem)
3643
37-
sample_transport = WebsocketsTransport(
44+
transport = WebsocketsTransport(
3845
url='wss://SERVER_URL:SERVER_PORT/graphql',
3946
ssl=ssl_context
4047
)
@@ -54,7 +61,7 @@ There are two ways to send authentication tokens with websockets depending on th
5461

5562
.. code-block:: python
5663
57-
sample_transport = WebsocketsTransport(
64+
transport = WebsocketsTransport(
5865
url='wss://SERVER_URL:SERVER_PORT/graphql',
5966
headers={'Authorization': 'token'}
6067
)
@@ -63,9 +70,53 @@ There are two ways to send authentication tokens with websockets depending on th
6370

6471
.. code-block:: python
6572
66-
sample_transport = WebsocketsTransport(
73+
transport = WebsocketsTransport(
6774
url='wss://SERVER_URL:SERVER_PORT/graphql',
6875
init_payload={'Authorization': 'token'}
6976
)
7077
78+
Keep-Alives
79+
-----------
80+
81+
Apollo protocol
82+
^^^^^^^^^^^^^^^
83+
84+
With the Apollo protocol, the backend can optionally send unidirectional keep-alive ("ka") messages
85+
(only from the server to the client).
86+
87+
It is possible to configure the transport to close if we don't receive a "ka" message
88+
within a specified time using the :code:`keep_alive_timeout` parameter.
89+
90+
Here is an example with 60 seconds::
91+
92+
transport = WebsocketsTransport(
93+
url='wss://SERVER_URL:SERVER_PORT/graphql',
94+
keep_alive_timeout=60,
95+
)
96+
97+
One disadvantage of the Apollo protocol is that because the keep-alives are only sent from the server
98+
to the client, it can be difficult to detect the loss of a connection quickly from the server side.
99+
100+
GraphQL-ws protocol
101+
^^^^^^^^^^^^^^^^^^^
102+
103+
With the GraphQL-ws protocol, it is possible to send bidirectional ping/pong messages.
104+
Pings can be sent either from the client or the server and the other party should answer with a pong.
105+
106+
As with the Apollo protocol, it is possible to configure the transport to close if we don't
107+
receive any message from the backend within the specified time using the :code:`keep_alive_timeout` parameter.
108+
109+
But there is also the possibility for the client to send pings at a regular interval and verify
110+
that the backend sends a pong within a specified delay.
111+
This can be done using the :code:`ping_interval` and :code:`pong_timeout` parameters.
112+
113+
Here is an example with a ping sent every 60 seconds, expecting a pong within 10 seconds::
114+
115+
transport = WebsocketsTransport(
116+
url='wss://SERVER_URL:SERVER_PORT/graphql',
117+
ping_interval=60,
118+
pong_timeout=10,
119+
)
120+
71121
.. _Apollo websockets transport protocol: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md
122+
.. _GraphQL-ws websockets transport protocol: https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md

0 commit comments

Comments
 (0)