Skip to content

Commit 3760f5b

Browse files
authored
Aws appsync websocket transport (#239)
Also refactor the websockets transport with WebsocketsTransportBase
1 parent 09e4b30 commit 3760f5b

35 files changed

+2704
-603
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ The complete documentation for GQL can be found at
3434

3535
The main features of GQL are:
3636

37-
* Execute GraphQL queries using [different protocols](https://gql.readthedocs.io/en/latest/transports/index.html) (http, websockets, ...)
37+
* Execute GraphQL queries using [different protocols](https://gql.readthedocs.io/en/latest/transports/index.html):
38+
* http
39+
* websockets:
40+
* apollo or graphql-ws protocol
41+
* Phoenix channels
42+
* AWS AppSync realtime protocol (experimental)
3843
* Possibility to [validate the queries locally](https://gql.readthedocs.io/en/latest/usage/validation.html) using a GraphQL schema provided locally or fetched from the backend using an instrospection query
3944
* Supports GraphQL queries, mutations and [subscriptions](https://gql.readthedocs.io/en/latest/usage/subscriptions.html)
4045
* Supports [sync or async usage](https://gql.readthedocs.io/en/latest/async/index.html), [allowing concurrent requests](https://gql.readthedocs.io/en/latest/advanced/async_advanced_usage.html#async-advanced-usage)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import asyncio
2+
import os
3+
import sys
4+
from urllib.parse import urlparse
5+
6+
from gql import Client, gql
7+
from gql.transport.aiohttp import AIOHTTPTransport
8+
from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
9+
10+
# Uncomment the following lines to enable debug output
11+
# import logging
12+
# logging.basicConfig(level=logging.DEBUG)
13+
14+
15+
async def main():
16+
17+
# Should look like:
18+
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
19+
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
20+
api_key = os.environ.get("AWS_GRAPHQL_API_KEY")
21+
22+
if url is None or api_key is None:
23+
print("Missing environment variables")
24+
sys.exit()
25+
26+
# Extract host from url
27+
host = str(urlparse(url).netloc)
28+
29+
auth = AppSyncApiKeyAuthentication(host=host, api_key=api_key)
30+
31+
transport = AIOHTTPTransport(url=url, auth=auth)
32+
33+
async with Client(
34+
transport=transport, fetch_schema_from_transport=False,
35+
) as session:
36+
37+
query = gql(
38+
"""
39+
mutation createMessage($message: String!) {
40+
createMessage(input: {message: $message}) {
41+
id
42+
message
43+
createdAt
44+
}
45+
}"""
46+
)
47+
48+
variable_values = {"message": "Hello world!"}
49+
50+
result = await session.execute(query, variable_values=variable_values)
51+
print(result)
52+
53+
54+
asyncio.run(main())
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import asyncio
2+
import os
3+
import sys
4+
from urllib.parse import urlparse
5+
6+
from gql import Client, gql
7+
from gql.transport.aiohttp import AIOHTTPTransport
8+
from gql.transport.appsync_auth import AppSyncIAMAuthentication
9+
10+
# Uncomment the following lines to enable debug output
11+
# import logging
12+
# logging.basicConfig(level=logging.DEBUG)
13+
14+
15+
async def main():
16+
17+
# Should look like:
18+
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
19+
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
20+
21+
if url is None:
22+
print("Missing environment variables")
23+
sys.exit()
24+
25+
# Extract host from url
26+
host = str(urlparse(url).netloc)
27+
28+
auth = AppSyncIAMAuthentication(host=host)
29+
30+
transport = AIOHTTPTransport(url=url, auth=auth)
31+
32+
async with Client(
33+
transport=transport, fetch_schema_from_transport=False,
34+
) as session:
35+
36+
query = gql(
37+
"""
38+
mutation createMessage($message: String!) {
39+
createMessage(input: {message: $message}) {
40+
id
41+
message
42+
createdAt
43+
}
44+
}"""
45+
)
46+
47+
variable_values = {"message": "Hello world!"}
48+
49+
result = await session.execute(query, variable_values=variable_values)
50+
print(result)
51+
52+
53+
asyncio.run(main())
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import asyncio
2+
import os
3+
import sys
4+
from urllib.parse import urlparse
5+
6+
from gql import Client, gql
7+
from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
8+
from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
9+
10+
# Uncomment the following lines to enable debug output
11+
# import logging
12+
# logging.basicConfig(level=logging.DEBUG)
13+
14+
15+
async def main():
16+
17+
# Should look like:
18+
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
19+
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
20+
api_key = os.environ.get("AWS_GRAPHQL_API_KEY")
21+
22+
if url is None or api_key is None:
23+
print("Missing environment variables")
24+
sys.exit()
25+
26+
# Extract host from url
27+
host = str(urlparse(url).netloc)
28+
29+
print(f"Host: {host}")
30+
31+
auth = AppSyncApiKeyAuthentication(host=host, api_key=api_key)
32+
33+
transport = AppSyncWebsocketsTransport(url=url, auth=auth)
34+
35+
async with Client(transport=transport) as session:
36+
37+
subscription = gql(
38+
"""
39+
subscription onCreateMessage {
40+
onCreateMessage {
41+
message
42+
}
43+
}
44+
"""
45+
)
46+
47+
print("Waiting for messages...")
48+
49+
async for result in session.subscribe(subscription):
50+
print(result)
51+
52+
53+
asyncio.run(main())
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
from gql import Client, gql
6+
from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
7+
8+
# Uncomment the following lines to enable debug output
9+
# import logging
10+
# logging.basicConfig(level=logging.DEBUG)
11+
12+
13+
async def main():
14+
15+
# Should look like:
16+
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
17+
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
18+
19+
if url is None:
20+
print("Missing environment variables")
21+
sys.exit()
22+
23+
# Using implicit auth (IAM)
24+
transport = AppSyncWebsocketsTransport(url=url)
25+
26+
async with Client(transport=transport) as session:
27+
28+
subscription = gql(
29+
"""
30+
subscription onCreateMessage {
31+
onCreateMessage {
32+
message
33+
}
34+
}
35+
"""
36+
)
37+
38+
print("Waiting for messages...")
39+
40+
async for result in session.subscribe(subscription):
41+
print(result)
42+
43+
44+
asyncio.run(main())

docs/intro.rst

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,23 @@ which needs the :code:`aiohttp` dependency, then you can install GQL with::
3535

3636
pip install --pre gql[aiohttp]
3737

38-
The corresponding between extra dependencies required and the GQL transports is:
39-
40-
+-------------------+----------------------------------------------------------------+
41-
| Extra dependency | Transports |
42-
+===================+================================================================+
43-
| aiohttp | :ref:`AIOHTTPTransport <aiohttp_transport>` |
44-
+-------------------+----------------------------------------------------------------+
45-
| websockets | :ref:`WebsocketsTransport <websockets_transport>` |
46-
| | |
47-
| | :ref:`PhoenixChannelWebsocketsTransport <phoenix_transport>` |
48-
+-------------------+----------------------------------------------------------------+
49-
| requests | :ref:`RequestsHTTPTransport <requests_transport>` |
50-
+-------------------+----------------------------------------------------------------+
38+
The corresponding between extra dependencies required and the GQL classes is:
39+
40+
+---------------------+----------------------------------------------------------------+
41+
| Extra dependencies | Classes |
42+
+=====================+================================================================+
43+
| aiohttp | :ref:`AIOHTTPTransport <aiohttp_transport>` |
44+
+---------------------+----------------------------------------------------------------+
45+
| websockets | :ref:`WebsocketsTransport <websockets_transport>` |
46+
| | |
47+
| | :ref:`PhoenixChannelWebsocketsTransport <phoenix_transport>` |
48+
| | |
49+
| | :ref:`AppSyncWebsocketsTransport <appsync_transport>` |
50+
+---------------------+----------------------------------------------------------------+
51+
| requests | :ref:`RequestsHTTPTransport <requests_transport>` |
52+
+---------------------+----------------------------------------------------------------+
53+
| botocore | :ref:`AppSyncIAMAuthentication <appsync_iam_auth>` |
54+
+---------------------+----------------------------------------------------------------+
5155

5256
.. note::
5357

docs/modules/gql.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ Sub-Packages
2020

2121
client
2222
transport
23+
transport_aiohttp
24+
transport_appsync_auth
25+
transport_appsync_websockets
2326
transport_exceptions
27+
transport_phoenix_channel_websockets
28+
transport_requests
29+
transport_websockets
30+
transport_websockets_base
2431
dsl
2532
utilities

docs/modules/transport.rst

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ gql.transport
55

66
.. autoclass:: gql.transport.transport.Transport
77

8-
.. autoclass:: gql.transport.local_schema.LocalSchemaTransport
9-
10-
.. autoclass:: gql.transport.requests.RequestsHTTPTransport
11-
128
.. autoclass:: gql.transport.async_transport.AsyncTransport
139

14-
.. autoclass:: gql.transport.aiohttp.AIOHTTPTransport
15-
16-
.. autoclass:: gql.transport.websockets.WebsocketsTransport
17-
18-
.. autoclass:: gql.transport.phoenix_channel_websockets.PhoenixChannelWebsocketsTransport
10+
.. autoclass:: gql.transport.local_schema.LocalSchemaTransport

docs/modules/transport_aiohttp.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
gql.transport.aiohttp
2+
=====================
3+
4+
.. currentmodule:: gql.transport.aiohttp
5+
6+
.. automodule:: gql.transport.aiohttp
7+
:member-order: bysource
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
gql.transport.appsync_auth
2+
==========================
3+
4+
.. currentmodule:: gql.transport.appsync_auth
5+
6+
.. automodule:: gql.transport.appsync_auth
7+
:member-order: bysource

0 commit comments

Comments
 (0)