Makes any REST API compatible with GraphQL requests.
It can:
- Sit as a standalone Flask app in front/behind your authentication layer, somewhere in between your frontend and services' APIs
- Communicate to services/APIs spanning multiple hosts
- Conform to different opinions of how REST should work
- Link together data from completely unrelated services/APIs in one frontend request
- Batch REST calls
It can't:
- Modify data
You must:
Here is a repository you can fork and use.
from functools import partial
import graphene
from graphql_to_rest import ExternalRESTField
class Hero(graphene.ObjectType):
base_url = "http://your-host/heroes"
id = graphene.ID()
name = graphene.String(name='name')
movies_appeared_in_ids = graphene.List(graphene.Int)
movies_appeared_in = ExternalRESTField(
partial(lambda: Movie),
source_field_name='movies_appeared_in_ids',
filter_field_name='id',
many=True
)
class Movie(graphene.ObjectType):
base_url = "http://another-host/movies"
id = graphene.ID()
name = graphene.String(name='name')
class Query(graphene.ObjectType):
heroes = ExternalRESTField(
Hero,
id=graphene.Argument(graphene.ID),
many=True,
is_top_level=True,
)
schema = graphene.Schema(query=Query)
import requests
import json
query = '''
{
heroes (id: "5") {
id
movies_appeared_in {
id
name
}
}
}
'''
data = {'query': query}
response = requests.get(
"http://graphql-app-host/graphql/",
data=json.dumps(data),
content_type='application/json'
)
print(response.json())
{"data": {
"heroes": [
{
"id": 5,
"movies_appeared_in": [
{"id": 1, "name": "Movie Name X"},
{"id": 2, "name": "Movie Name Y"}
]}]}}
# the request to http://graphql-app-host/graphql makes two requests to the heroes endpoint:
# GET http://your-host/heroes?id=5
# GET http://another-host/movies?id=1,2
py.test
py.test --capture=no # if you want to `import pytest; pytest.set_trace()`