ASGI support for the Tartiflette Python GraphQL engine
Project description
tartiflette-starlette is a wrapper that provides ASGI support for the Tartiflette Python GraphQL engine.
Build your GraphQL API with Tartiflette, then use the included TartifletteApp and get the following:
- Compatibility with any ASGI server and framework.
- Standalone and sub-app serving.
- Built-in GraphiQL client.
Note: WebSocket subscriptions aren't supported yet.
Table of contents
Quickstart
from tartiflette import Resolver
from tartiflette_starlette import TartifletteApp
@Resolver("Query.hello")
async def hello(parent, args, context, info):
name = args["name"]
return f"Hello, {name}!"
sdl = """
type Query {
hello(name: String): String
}
"""
app = TartifletteApp(sdl=sdl)
Save the file as graphql.py and start a uvicorn server:
uvicorn graphql:app
Note: the GraphQL endpoint is exposed on
/by default.
Make a request:
curl -H "Content-Type: application/graphql" -d '{ hello(name: "Chuck") }' http://localhost:8000
Response:
{ "data": { "hello": "Hello, Chuck!" } }
Or access http://localhost:8000 in a browser to make interactive queries using the built-in GraphiQL client:
Installation
- Install Tartiflette's external dependencies as explained in the Tartiflette tutorial.
- Install
tartiflette-starlettefrom PyPI:
pip install tartiflette-starlette
This will also install Tartiflette and Starlette, so you're good to go!
Note: tartiflette-starlette requires Python 3.6+.
User guide
The TartifletteApp class is an ASGI3-compliant application. There are two ways to use it:
- Serve it as a standalone ASGI app.
- Mount it as an endpoint of another ASGI app (e.g. a Starlette application).
Standalone serving
The Quickstart example shows how to build a TartifletteApp and serve it as a standalone ASGI app.
The app is served using Uvicorn, but any other ASGI web server will do, for example:
ASGI submounting
Most ASGI web frameworks provide a way to mount another ASGI app at a given URL prefix. You can use this to serve a TartifletteApp at an endpoint such as /graphql on the root ASGI application.
This is useful to have a GraphQL endpoint and other (non-GraphQL) endpoints within a single application. For example, to have a REST endpoint at /api/users and a GraphQL endpoint at /graphql.
Important: this should work with any web framework that supports ASGI submounting — it doesn't have to be Starlette. See also: What is the role of Starlette?
Starlette example
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from tartiflette import Resolver
from tartiflette_starlette import TartifletteApp, mount
app = Starlette()
@app.route("/")
async def home(request):
return PlainTextResponse("Hello, world!")
@Resolver("Query.hello")
async def hello(parent, args, context, info):
name = args["name"]
return f"Hello, {name}!"
sdl = """
type Query {
hello(name: String): String
}
"""
graphql = TartifletteApp(sdl=sdl)
mount.starlette(app, "/graphql", graphql) # (*)
(*) This is a shorthand for:
app.mount("/graphql", graphql) app.add_event_handler("startup", graphql.startup)
Save the file as app.py, and serve it with uvicorn:
uvicorn app:app
Make a request:
curl -H "Content-Type: application/graphql" -d '{ hello(name: "Chuck") }' http://localhost:8000
Response:
{ "data": { "hello": "Hello, Chuck!" } }
General approach
Assuming you have an instance of TartifletteApp called graphql, you need to:
- Add the
graphqlapp as a sub-application (also known as "mounting"). The parent ASGI application may expose a method such as.mount()for this purpose. - Add
graphql.startupas a startup event handler so that the Tartiflette engine is built upon application startup. Note that:
- Not doing this will result in a
RuntimeErrorwhen requesting the GraphQL endpoint. - The parent ASGI application may expose a method such as
.add_event_handler()for this purpose. - This is only required if the parent ASGI application does not call lifespan event handlers for sub-applications, as is the case for Starlette.
Tip: the mount module provides mounting helpers for various ASGI frameworks.
Making requests
tartiflette-starlette complies with the GraphQL spec, which allows you to pass the query in several ways:
- URL query string (methods:
GET,POST):
curl 'http://localhost:8000?query=\{hello(name:"Chuck")\}'
- JSON-encoded body (methods:
POST):
curl \
-H "Content-Type: application/json" \
-d '{"query": "{ hello(name: \"Chuck\") }"}' \
http://localhost:8000
- Raw body with the
application/graphqlcontent type (methods:POST):
curl \
-H "Content-Type: application/graphql" \
-d '{ hello(name: "Chuck") }' \
http://localhost:8000
Note: you may have your GraphQL API served at a different endpoint.
Accessing request information
You can access the Starlette Request object from resolvers using context["req"]:
@Resolver("Query.whoami")
async def resolve_whoami(parent, args, context, info) -> str:
request = context["req"]
return getattr(request.state, "user", "a mystery")
See also Requests in the Starlette documentation.
GraphiQL client
By default, the GraphQL endpoint provided by TartifletteApp serves a GraphiQL client when it is accessed from a web browser. It can be customized using the GraphiQL helper.
Here's an example:
from tartiflette_starlette import TartifletteApp, GraphiQL
app = TartifletteApp(
sdl="""
type Query {
hello(name: String): String
}
""",
graphiql=GraphiQL(
path="/graphiql",
default_headers={"Authorization": "Bearer 123"},
default_variables={"name": "world"},
default_query="""
query Hello($name: String) {
hello(name: $name)
}
""",
),
)
Save this as graphql.py and run uvicorn graphql:app. You should see the customized GraphiQL client when accessing http://127.0.0.1/graphiql:
See GraphiQL in the API reference for a complete description of the available options.
API Reference
Note: unless specified, components documented here can be imported from
tartiflette_starlettedirectly, e.g.from tartiflette_starlette import TartifletteApp.
TartifletteApp
Parameters
Note: all parameters are keyword-only.
engine(Engine): a Tartiflette engine. Required ifsdlis not given.sdl(str): a GraphQL schema defined using the GraphQL Schema Definition Language. Required ifengineis not given.graphiql(GraphiQLorbool, optional): configuration for the GraphiQL client. Defaults toTrue, which is equivalent toGraphiQL(). UseFalseto not register the GraphiQL client.path(str, optional): the path which clients should make GraphQL queries to. Defaults to"/".schema_name(str, optional): name of the GraphQL schema from the Schema Registry which should be used — mostly for advanced usage. Defaults to"default".
Methods
__call__(scope, receive, send): ASGI3 implementation.
Error responses
| Status code | Description |
|---|---|
| 400 Bad Request | The GraphQL query could not be found in the request data. |
| 404 Not Found | The request does not match the GraphQL or GraphiQL endpoint paths. |
| 405 Method Not Allowed | The HTTP method is not one of GET, HEAD or POST. |
| 415 Unsupported Media Type | The POST request made to the GraphQL endpoint uses a Content-Type different from application/json and application/graphql. |
GraphiQL
Configuration helper for the GraphiQL client.
Parameters
Note: all parameters are keyword-only.
path(str, optional): the path of the GraphiQL endpoint, relative to the root path whichTartifletteAppis served at. If not given, defaults to thepathgiven toTartifletteApp.default_headers(dict, optional): extra HTTP headers to send when calling the GraphQL endpoint.default_query(str, optional): the default query to display when accessing the GraphiQL interface.default_variables(dict, optional): default variables to display when accessing the GraphiQL interface.template(str, optional): an HTML template to use instead of the default one. In the template,default_headers,default_queryanddefault_variables, as well as the GraphQLendpoint, are available as strings (JSON-encoded if needed) using template string substitutions, e.g.:
const endpoint = `${endpoint}`; // This is where the API call should be made.
const defaultHeaders = JSON.parse(`${default_headers}`);
mount
This module contains helpers for mounting a TartifletteApp on other ASGI applications. Use these helpers to make sure you comply with the steps described in General approach.
Parameters
All mounting helpers expect the same parameters:
parent(ASGI app): the parent ASGI application which theTartifletteAppmust be mounted onto.path(str): the URL path where theTartifletteAppshould be mounted.app(TartifletteApp): theTartifletteAppto mount.**kwargs(any): extra keyword arguments passed to the mount implementation of theparentapp.
Available helpers
| Helper | Mount implementation | Startup event handler implementation |
|---|---|---|
mount.starlette() |
parent.mount() |
parent.add_event_handler() |
Missing a helper for your favorite framework? Feel free to open a pull request!
FAQ
Does this package ship with Tartiflette?
Yes. Everything is included, which allows you to start building your GraphQL API right away. See also Installation.
Do I need to learn GraphQL/Tartiflette to use this package?
Yes: once you've got the TartifletteApp ASGI app up and running, you're in Tartiflette territory.
Here are some resources to get you started:
What is the role of Starlette?
tartiflette-starlette uses Starlette as a lightweight ASGI toolkit: internally, it uses Starlette's request and response classes, and some other components.
Luckily, this does not require your applications to use Starlette at all.
For example, if you are submounting your GraphQL app on an app built with an async web framework, this framework does not need to use Starlette — it just needs to speak ASGI.
What is ASGI?
ASGI provides a standard interface between async-capable Python web servers, frameworks, and applications.
See also the ASGI documentation.
Contributing
Want to contribute? Awesome! Be sure to read our Contributing guidelines.
Changelog
Changes to this project are recorded in the changelog.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tartiflette-starlette-0.4.0.tar.gz.
File metadata
- Download URL: tartiflette-starlette-0.4.0.tar.gz
- Upload date:
- Size: 16.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a34a9d3a2c22d13d1806f380636025393df4a494f939bbfa421a252cdf7e0a7d
|
|
| MD5 |
a4df4719f0ffaa9b3ec7009cdbf62614
|
|
| BLAKE2b-256 |
afbc67d7eec11078aa52debd166a89bb501a35d542cd18ba2c186bac4b0f411e
|
File details
Details for the file tartiflette_starlette-0.4.0-py3-none-any.whl.
File metadata
- Download URL: tartiflette_starlette-0.4.0-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b69c9396d46c359118c6e89a73208d0fe4af9293163fee990ec9083a15d407b6
|
|
| MD5 |
08f008445b3edf46ce2f0101e29ae641
|
|
| BLAKE2b-256 |
691bd39e510b79666c9f40273226879f48e491cb183664f997ccbb9f97f9c884
|