I'm using Uvicorn and Starlette with Ariadne for GraphQL queries, but the GraphQL handler does not seem to be working.
I'm using poetry so this is what my pyproject.toml
file looks like:
[tool.poetry]
name = "app-backend"
version = "0.1.0"
description = ""
authors = ["user <email@gmail.com>"]
license = "BSD-2"
packages = [
{ include="api", from="." }
]
[tool.poetry.dependencies]
python = "^3.10"
ariadne = "=0.16.1"
alembic = "1.8.1"
psycopg2-binary = "2.9.4"
PyJWT = "^2.3.0"
starlette = "0.20.4"
"marrow.mailer" = "^4.0.3"
gunicorn = "^20.1.0"
python-multipart = "^0.0.5"
SQLAlchemy = "1.4.42"
rauth = "^0.7.3"
aiohttp = "3.8.3"
aiofiles = "22.1.0"
SQLAlchemy-Utils = "^0.38.3"
BroadCast = "^1.1.2"
broadcaster = {extras = ["postgres"], version = "^0.2.0"}
websockets = "^10.3"
graphql-core = "3.2.3"
anyio = "3.6.2"
uvicorn = {extras = ["standard"], version = "^0.19.0"}
pytest = "^7.1.3"
[tool.poetry.scripts]
init_app = "api.scripts.initial_config:main"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
This is my code
import uvicorn
import asyncio
from ariadne.asgi import GraphQL
from ariadne.asgi.handlers import GraphQLTransportWSHandler
from ariadne import MutationType, make_executable_schema
from starlette.applications import Starlette
from starlette.routing import (Route, WebSocketRoute)
type_defs = """
type Query {
_unused: Boolean
}
type Message {
sender: String
message: String
}
type Mutation {
send(sender: String!, message: String!): Boolean
}
type Subscription {
message: Message
}
"""
mutation = MutationType()
schema = make_executable_schema(type_defs, mutation)
graphql_handler = GraphQL(
schema=schema,
debug=True,
introspection=True,
websocket_handler=GraphQLTransportWSHandler(),
logger="admin.graphql"
)
routes = [
Route("/api/graphql", graphql_handler, name="graphql"),
WebSocketRoute("/api/subscriptions", endpoint=graphql_handler.websocket_handler, name="graphqlws"),
]
app = Starlette(routes=routes)
async def main():
config = uvicorn.Config("main:app", port=8000, log_level="info", log_config="log.json", ws="websockets")
server = uvicorn.Server(config)
await server.serve()
if __name__ == "__main__":
asyncio.run(main())
Which I'm running like this:
poetry run python3 main2.py
But trying to open a new websocket connection seems to fail:
new WebSocket('ws://localhost:8000/api/subscriptions');
I get the following errors:
Traceback (most recent call last):
File "<...>/lib/python3.10/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 230, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
File "<...>/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/middleware/errors.py", line 149, in __call__
await self.app(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/middleware/cors.py", line 76, in __call__
await self.app(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/middleware/authentication.py", line 48, in __call__
await self.app(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/middleware/base.py", line 24, in __call__
await self.app(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 51, in __call__
await self.app(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/routing.py", line 680, in __call__
await route.handle(scope, receive, send)
File "<...>/lib/python3.10/site-packages/starlette/routing.py", line 334, in handle
await self.app(scope, receive, send)
TypeError: 'GraphQLTransportWSHandler' object is not callable
I've looked at Ariadne's docs on subscriptions and, although using websocket_handler on a websocket route is not documented (it was clarified on one of ariadne's PR's), neither is this behaviour.
Is there something I missed?