Skip to content

Aws appsync websocket transport #239

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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
26e2d0d
chore: registered new pytest mark
chadfurman Sep 13, 2021
d4c8a7b
chore: added botocore dependency
chadfurman Sep 13, 2021
8535f5e
test: initial test for appsyncwebsocket before I started coyp/pasting…
chadfurman Sep 13, 2021
149d788
feat: wip aws appsync websocket code inspired / copied extensively fr…
chadfurman Sep 13, 2021
4d099e7
fix: added url munging and cleaned up _send_query to avoid having to …
chadfurman Sep 19, 2021
5cb3c33
test: wip test coverage. Added coverage for munge_url during init an…
chadfurman Sep 19, 2021
ccea6ad
Merge branch 'master' into aws-appsync-websocket-transport
chadfurman Sep 26, 2021
0fddb4f
test: started fixing unit tests. Looks like credentials are not bein…
chadfurman Sep 27, 2021
246d2cc
test: added more dependency injection and fakes for aws. New error, …
chadfurman Sep 27, 2021
07c9ae4
tests: cleaned up awsappsyncwebsocket and related tests so that they …
chadfurman Sep 29, 2021
25cde97
fix: make check applied, flake errors fixed
chadfurman Oct 4, 2021
6cb8c83
fix: added 'aws' as an install target for tests
chadfurman Oct 4, 2021
c8bafa4
fix: typehint issues addressed
chadfurman Oct 10, 2021
ee0496d
test: updated iam test without credentials to explicitly trigger cred…
chadfurman Oct 10, 2021
b9a61b7
chore: registered new pytest mark
chadfurman Sep 13, 2021
45aa769
chore: added botocore dependency
chadfurman Sep 13, 2021
b1fe6b0
test: initial test for appsyncwebsocket before I started coyp/pasting…
chadfurman Sep 13, 2021
3f28592
feat: wip aws appsync websocket code inspired / copied extensively fr…
chadfurman Sep 13, 2021
d37c769
fix: added url munging and cleaned up _send_query to avoid having to …
chadfurman Sep 19, 2021
9bd8d93
test: wip test coverage. Added coverage for munge_url during init an…
chadfurman Sep 19, 2021
5ea673b
test: started fixing unit tests. Looks like credentials are not bein…
chadfurman Sep 27, 2021
7ae6786
test: added more dependency injection and fakes for aws. New error, …
chadfurman Sep 27, 2021
3a025d8
tests: cleaned up awsappsyncwebsocket and related tests so that they …
chadfurman Sep 29, 2021
6dd9de9
fix: make check applied, flake errors fixed
chadfurman Oct 4, 2021
887ed59
fix: added 'aws' as an install target for tests
chadfurman Oct 4, 2021
90c121a
fix: typehint issues addressed
chadfurman Oct 10, 2021
1ac1350
test: updated iam test without credentials to explicitly trigger cred…
chadfurman Oct 10, 2021
1515378
Merge remote-tracking branch 'origin/aws-appsync-websocket-transport'…
chadfurman Oct 11, 2021
7b75fd5
fix: linting errors
chadfurman Oct 11, 2021
86ddc13
fix: test marker adjusted, renamed
chadfurman Oct 11, 2021
d798001
fix: running 'make check' to fix module sort order
leszekhanusz Oct 26, 2021
2ef43eb
fix: tests put imports inside methods to fix tests without botocore
leszekhanusz Oct 26, 2021
9f09db6
Merge branch 'master' into aws-appsync-websocket-transport
leszekhanusz Oct 26, 2021
5633d82
Merge branch 'master' into aws-appsync-websocket-transport
leszekhanusz Nov 29, 2021
aa9cb06
Multiple fixes:
leszekhanusz Nov 29, 2021
adf5a38
Add AWS code examples
leszekhanusz Nov 30, 2021
8d07646
Rename file awsappsyncwebsockets.py to awsappsync.py
leszekhanusz Nov 30, 2021
7552bac
setup.py allow more recent versions of botocore
leszekhanusz Nov 30, 2021
590239d
IAM auth: fix host instead of url and headers
leszekhanusz Dec 1, 2021
9ce4fa6
Fix IAM auth
leszekhanusz Dec 1, 2021
ad80541
fix IAM tests
leszekhanusz Dec 1, 2021
dfee6db
add typing to AppSyncIAMAuthorization
leszekhanusz Dec 2, 2021
850ad91
Refactor parse_answer to have json.loads happening only once
leszekhanusz Dec 2, 2021
fe22631
Adding some documentation
leszekhanusz Dec 2, 2021
413c651
Rename awsappsync.py to appsync.py
leszekhanusz Dec 2, 2021
9aad6ff
Split WebsocketsTransport into WebsocketsTransportBase and Websockets…
leszekhanusz Dec 2, 2021
6b79fe4
AppSyncWebsocketsTransport now inherits WebsocketsTransportBase
leszekhanusz Dec 2, 2021
23f7247
Refactor: split websockets.py into websockets.py and websockets_base.py
leszekhanusz Dec 2, 2021
2f199f0
Disallow execute on appsync transport + change subscribe doc message
leszekhanusz Dec 2, 2021
9fd9faf
Rename extra dependency from appsyncwebsockets to appsync + add to in…
leszekhanusz Dec 2, 2021
c5408bb
Rename Authorization to Authentication
leszekhanusz Dec 2, 2021
3b18158
Add simulated AppSync backend tests
leszekhanusz Dec 3, 2021
4cec1dd
Only one auth class for JWT
leszekhanusz Dec 3, 2021
35af8ce
Fix tests host/url confusion
leszekhanusz Dec 3, 2021
bfe99a5
rename test_appsyncwebsocket.py to test_appsync_auth.py
leszekhanusz Dec 3, 2021
5efc660
small modif: print Region found if region test fails
leszekhanusz Dec 3, 2021
f3446e6
Add region_name in tests
leszekhanusz Dec 3, 2021
69147e6
By default try to get the region from the host
leszekhanusz Dec 3, 2021
b271a1c
Improve documentation
leszekhanusz Dec 4, 2021
1f6f2c4
api_key is not needed in iam example
leszekhanusz Dec 4, 2021
db4a710
Fix AttributeError('AppSyncWebsocketsTransport' object has no attribu…
leszekhanusz Dec 5, 2021
a5874d4
Split appsync.py into 2 files
leszekhanusz Dec 5, 2021
500c635
Put appsync code examples in separate folder
leszekhanusz Dec 6, 2021
ffd4bf1
Doc code examples comment debug logging
leszekhanusz Dec 6, 2021
715bc62
botocore dependency needed only for IAM auth
leszekhanusz Dec 6, 2021
8873afe
add websockets_base module to docs
leszekhanusz Dec 6, 2021
bb31922
add appsync http iam test
leszekhanusz Dec 6, 2021
2526274
fix mark websockets missing on some appsync auth tests
leszekhanusz Dec 6, 2021
9224701
remove redundant line in test_appsync_http.py
leszekhanusz Dec 6, 2021
1952302
Docs: Add reference blog post to create the sample app
leszekhanusz Dec 6, 2021
34dbd3e
README.md add AWS AppSync to features
leszekhanusz Dec 6, 2021
e35537e
Remove markers from tox.ini
leszekhanusz Dec 6, 2021
9b85b99
Merge branch 'master' into aws-appsync-websocket-transport
leszekhanusz Dec 9, 2021
4439121
Merge branch 'master' into aws-appsync-websocket-transport
leszekhanusz Dec 10, 2021
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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ The complete documentation for GQL can be found at

The main features of GQL are:

* Execute GraphQL queries using [different protocols](https://gql.readthedocs.io/en/latest/transports/index.html) (http, websockets, ...)
* Execute GraphQL queries using [different protocols](https://gql.readthedocs.io/en/latest/transports/index.html):
* http
* websockets:
* apollo or graphql-ws protocol
* Phoenix channels
* AWS AppSync realtime protocol (experimental)
* 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
* Supports GraphQL queries, mutations and [subscriptions](https://gql.readthedocs.io/en/latest/usage/subscriptions.html)
* 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)
Expand Down
54 changes: 54 additions & 0 deletions docs/code_examples/appsync/mutation_api_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import asyncio
import os
import sys
from urllib.parse import urlparse

from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport
from gql.transport.appsync_auth import AppSyncApiKeyAuthentication

# Uncomment the following lines to enable debug output
# import logging
# logging.basicConfig(level=logging.DEBUG)


async def main():

# Should look like:
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
api_key = os.environ.get("AWS_GRAPHQL_API_KEY")

if url is None or api_key is None:
print("Missing environment variables")
sys.exit()

# Extract host from url
host = str(urlparse(url).netloc)

auth = AppSyncApiKeyAuthentication(host=host, api_key=api_key)

transport = AIOHTTPTransport(url=url, auth=auth)

async with Client(
transport=transport, fetch_schema_from_transport=False,
) as session:

query = gql(
"""
mutation createMessage($message: String!) {
createMessage(input: {message: $message}) {
id
message
createdAt
}
}"""
)

variable_values = {"message": "Hello world!"}

result = await session.execute(query, variable_values=variable_values)
print(result)


asyncio.run(main())
53 changes: 53 additions & 0 deletions docs/code_examples/appsync/mutation_iam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import asyncio
import os
import sys
from urllib.parse import urlparse

from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport
from gql.transport.appsync_auth import AppSyncIAMAuthentication

# Uncomment the following lines to enable debug output
# import logging
# logging.basicConfig(level=logging.DEBUG)


async def main():

# Should look like:
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")

if url is None:
print("Missing environment variables")
sys.exit()

# Extract host from url
host = str(urlparse(url).netloc)

auth = AppSyncIAMAuthentication(host=host)

transport = AIOHTTPTransport(url=url, auth=auth)

async with Client(
transport=transport, fetch_schema_from_transport=False,
) as session:

query = gql(
"""
mutation createMessage($message: String!) {
createMessage(input: {message: $message}) {
id
message
createdAt
}
}"""
)

variable_values = {"message": "Hello world!"}

result = await session.execute(query, variable_values=variable_values)
print(result)


asyncio.run(main())
53 changes: 53 additions & 0 deletions docs/code_examples/appsync/subscription_api_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import asyncio
import os
import sys
from urllib.parse import urlparse

from gql import Client, gql
from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

# Uncomment the following lines to enable debug output
# import logging
# logging.basicConfig(level=logging.DEBUG)


async def main():

# Should look like:
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
api_key = os.environ.get("AWS_GRAPHQL_API_KEY")

if url is None or api_key is None:
print("Missing environment variables")
sys.exit()

# Extract host from url
host = str(urlparse(url).netloc)

print(f"Host: {host}")

auth = AppSyncApiKeyAuthentication(host=host, api_key=api_key)

transport = AppSyncWebsocketsTransport(url=url, auth=auth)

async with Client(transport=transport) as session:

subscription = gql(
"""
subscription onCreateMessage {
onCreateMessage {
message
}
}
"""
)

print("Waiting for messages...")

async for result in session.subscribe(subscription):
print(result)


asyncio.run(main())
44 changes: 44 additions & 0 deletions docs/code_examples/appsync/subscription_iam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import asyncio
import os
import sys

from gql import Client, gql
from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

# Uncomment the following lines to enable debug output
# import logging
# logging.basicConfig(level=logging.DEBUG)


async def main():

# Should look like:
# https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")

if url is None:
print("Missing environment variables")
sys.exit()

# Using implicit auth (IAM)
transport = AppSyncWebsocketsTransport(url=url)

async with Client(transport=transport) as session:

subscription = gql(
"""
subscription onCreateMessage {
onCreateMessage {
message
}
}
"""
)

print("Waiting for messages...")

async for result in session.subscribe(subscription):
print(result)


asyncio.run(main())
30 changes: 17 additions & 13 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,23 @@ which needs the :code:`aiohttp` dependency, then you can install GQL with::

pip install --pre gql[aiohttp]

The corresponding between extra dependencies required and the GQL transports is:

+-------------------+----------------------------------------------------------------+
| Extra dependency | Transports |
+===================+================================================================+
| aiohttp | :ref:`AIOHTTPTransport <aiohttp_transport>` |
+-------------------+----------------------------------------------------------------+
| websockets | :ref:`WebsocketsTransport <websockets_transport>` |
| | |
| | :ref:`PhoenixChannelWebsocketsTransport <phoenix_transport>` |
+-------------------+----------------------------------------------------------------+
| requests | :ref:`RequestsHTTPTransport <requests_transport>` |
+-------------------+----------------------------------------------------------------+
The corresponding between extra dependencies required and the GQL classes is:

+---------------------+----------------------------------------------------------------+
| Extra dependencies | Classes |
+=====================+================================================================+
| aiohttp | :ref:`AIOHTTPTransport <aiohttp_transport>` |
+---------------------+----------------------------------------------------------------+
| websockets | :ref:`WebsocketsTransport <websockets_transport>` |
| | |
| | :ref:`PhoenixChannelWebsocketsTransport <phoenix_transport>` |
| | |
| | :ref:`AppSyncWebsocketsTransport <appsync_transport>` |
+---------------------+----------------------------------------------------------------+
| requests | :ref:`RequestsHTTPTransport <requests_transport>` |
+---------------------+----------------------------------------------------------------+
| botocore | :ref:`AppSyncIAMAuthentication <appsync_iam_auth>` |
+---------------------+----------------------------------------------------------------+

.. note::

Expand Down
7 changes: 7 additions & 0 deletions docs/modules/gql.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ Sub-Packages

client
transport
transport_aiohttp
transport_appsync_auth
transport_appsync_websockets
transport_exceptions
transport_phoenix_channel_websockets
transport_requests
transport_websockets
transport_websockets_base
dsl
utilities
10 changes: 1 addition & 9 deletions docs/modules/transport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ gql.transport

.. autoclass:: gql.transport.transport.Transport

.. autoclass:: gql.transport.local_schema.LocalSchemaTransport

.. autoclass:: gql.transport.requests.RequestsHTTPTransport

.. autoclass:: gql.transport.async_transport.AsyncTransport

.. autoclass:: gql.transport.aiohttp.AIOHTTPTransport

.. autoclass:: gql.transport.websockets.WebsocketsTransport

.. autoclass:: gql.transport.phoenix_channel_websockets.PhoenixChannelWebsocketsTransport
.. autoclass:: gql.transport.local_schema.LocalSchemaTransport
7 changes: 7 additions & 0 deletions docs/modules/transport_aiohttp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.aiohttp
=====================

.. currentmodule:: gql.transport.aiohttp

.. automodule:: gql.transport.aiohttp
:member-order: bysource
7 changes: 7 additions & 0 deletions docs/modules/transport_appsync_auth.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.appsync_auth
==========================

.. currentmodule:: gql.transport.appsync_auth

.. automodule:: gql.transport.appsync_auth
:member-order: bysource
7 changes: 7 additions & 0 deletions docs/modules/transport_appsync_websockets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.appsync_websockets
================================

.. currentmodule:: gql.transport.appsync_websockets

.. automodule:: gql.transport.appsync_websockets
:member-order: bysource
7 changes: 7 additions & 0 deletions docs/modules/transport_phoenix_channel_websockets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.phoenix_channel_websockets
========================================

.. currentmodule:: gql.transport.phoenix_channel_websockets

.. automodule:: gql.transport.phoenix_channel_websockets
:member-order: bysource
7 changes: 7 additions & 0 deletions docs/modules/transport_requests.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.requests
======================

.. currentmodule:: gql.transport.requests

.. automodule:: gql.transport.requests
:member-order: bysource
7 changes: 7 additions & 0 deletions docs/modules/transport_websockets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.websockets
========================

.. currentmodule:: gql.transport.websockets

.. automodule:: gql.transport.websockets
:member-order: bysource
7 changes: 7 additions & 0 deletions docs/modules/transport_websockets_base.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
gql.transport.websockets_base
=============================

.. currentmodule:: gql.transport.websockets_base

.. automodule:: gql.transport.websockets_base
:member-order: bysource
Loading