/graphql-to-rest

Makes any REST API compatible with GraphQL

Primary LanguagePythonApache License 2.0Apache-2.0

graphql-to-REST

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:

  • Define your API schema in graphene (example below)
  • Run a flask app like this somewhere

Example Usage

Here is a repository you can fork and use.

Schema definition

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)

GraphQL Request / Response

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

Testing

py.test
py.test --capture=no # if you want to `import pytest; pytest.set_trace()`

Build next