Skip to content

Allow to specify subprotocols in the websockets transport #300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/transports/websockets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ The websockets transport supports both:
- the `Apollo websockets transport protocol`_.
- the `GraphQL-ws websockets transport protocol`_

It will detect the backend supported protocol from the response http headers returned.
It will propose both subprotocols to the backend and detect the supported protocol
from the response http headers returned by the backend.

.. note::
For some backends (graphql-ws before `version 5.6.1`_ without backwards compatibility), it may be necessary to specify
only one subprotocol to the backend. It can be done by using
:code:`subprotocols=[WebsocketsTransport.GRAPHQLWS_SUBPROTOCOL]`
or :code:`subprotocols=[WebsocketsTransport.APOLLO_SUBPROTOCOL]` in the transport arguments.

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

Expand Down Expand Up @@ -118,5 +125,6 @@ Here is an example with a ping sent every 60 seconds, expecting a pong within 10
pong_timeout=10,
)

.. _version 5.6.1: https://github.com/enisdenjo/graphql-ws/releases/tag/v5.6.1
.. _Apollo websockets transport protocol: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md
.. _GraphQL-ws websockets transport protocol: https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
17 changes: 12 additions & 5 deletions gql/transport/websockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from contextlib import suppress
from ssl import SSLContext
from typing import Any, Dict, Optional, Tuple, Union, cast
from typing import Any, Dict, List, Optional, Tuple, Union, cast

from graphql import DocumentNode, ExecutionResult, print_ast
from websockets.datastructures import HeadersLike
Expand Down Expand Up @@ -46,6 +46,7 @@ def __init__(
pong_timeout: Optional[Union[int, float]] = None,
answer_pings: bool = True,
connect_args: Dict[str, Any] = {},
subprotocols: Optional[List[Subprotocol]] = None,
) -> None:
"""Initialize the transport with the given parameters.

Expand All @@ -71,6 +72,9 @@ def __init__(
(for the graphql-ws protocol).
By default: True
:param connect_args: Other parameters forwarded to websockets.connect
:param subprotocols: list of subprotocols sent to the
backend in the 'subprotocols' http header.
By default: both apollo and graphql-ws subprotocols.
"""

super().__init__(
Expand Down Expand Up @@ -105,10 +109,13 @@ def __init__(
"""pong_received is an asyncio Event which will fire each time
a pong is received with the graphql-ws protocol"""

self.supported_subprotocols = [
self.APOLLO_SUBPROTOCOL,
self.GRAPHQLWS_SUBPROTOCOL,
]
if subprotocols is None:
self.supported_subprotocols = [
self.APOLLO_SUBPROTOCOL,
self.GRAPHQLWS_SUBPROTOCOL,
]
else:
self.supported_subprotocols = subprotocols

async def _wait_ack(self) -> None:
"""Wait for the connection_ack message. Keep alive messages are ignored"""
Expand Down
4 changes: 3 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,9 @@ async def client_and_graphqlws_server(graphqlws_server):
# Generate transport to connect to the server fixture
path = "/graphql"
url = f"ws://{graphqlws_server.hostname}:{graphqlws_server.port}{path}"
sample_transport = WebsocketsTransport(url=url)
sample_transport = WebsocketsTransport(
url=url, subprotocols=[WebsocketsTransport.GRAPHQLWS_SUBPROTOCOL],
)

async with Client(transport=sample_transport) as session:

Expand Down