Wrapping a REST API in GraphQL

Joe Ng'ethe
6 min readJun 7, 2018

GraphQL has been, for the last couple of years, been one of the ‘hottest stack’ in the tech scene and it has continued to be adopted by many companies for the benefits it brings. Some have claimed that GraphQL will be the REST killer of which, I think, isn’t entirely true in my opinion.

One thing I can attest to is the benefits that GraphQL brings to the table when you are building web and mobile applications. I am not going to talk about the benefits in this post but you can learn about them here and about the similarities and differences here

Instead, I am going to show you how you can start using GraphQL without changing your current architecture and with the least investment possible. Let’s get right to it.

What we are going to build

GraphQL Playground

We are going to build a Star Wars GraphQL API from a REST API that will let you query for characters using the People field — which will have a PersonType and it will expose the following fields

  • Name
  • Gender
  • Vehicles
  • Films
  • Species
  • Starships

The above fields will each have a GraphQL<type> depending on the shape of the returned value. I will explain expound on GraphQLTypes in the next section.

GraphQL Schema, Object types and Fields

Let’s have a look at our schema and the fields we want to expose to our API.

The most basic components of a GraphQL schema are object types, which just represent a kind of object you can fetch from your service, and what fields it has.

For instance, in our API we will define a PersonType which will be of type GraphQLObjectType and will have a couple of properties attached to it as follows;

  • name: This is the name property that we will use to query with.
  • description: Is an optional description and acts as some sort of documentation for other devs in your team who will be consuming the API
  • fields: property is a function that returns an object with other fields attached to the root property. In our case, a PersonType will have the following fields; name, gender, vehicles, species, films, starships all of which will be of either of type GraphQLString meaning it’s value will be a string or GraphQLList(GraphQLString) meaning that it returns an array containing strings.
  • resolve: which is a function that returns a value attached to the field name property. The fact that this is a function that can return any value is huge for it opens up so many possibilities. It means we can return a <Promise> from some API among other things. This means you can do something like;
....gender: {  type: GraphQLString,  description: 'A star wars gender',  resolve: () => fetch(`${BASE_URL}/people/${args.id}`)    .then(response => response.json())    .then(person => person.gender)}...

See the simplified schema below of the PersonType that we will use so as you have an idea.

const PersonType = new GraphQLObjectType({  name: 'Person',  description: 'A star wars Character',  fields: () => ({    name: {      type: GraphQLString,      description: 'A character\'s  name',      resolve: (person) => person.name    },
gender: {
type: GraphQLString, description: 'A character\'s gender', resolve: (person) => person.gender }, })});

As for our REST API, we will use the Star Wars API . This can be any REST API that you currently have setup and the same principles and concepts should work.

The code and how to run it

At this point I assume that you have node installed. If not, download and install it here.

Follow the steps and commands below;

git clone git@github.com:joeynimu/graphql-user-api.git
  • Change directory and install dependancies by runningcd graphql-user-api && npm install
  • Start the application by running npm start . At this point you should see something like this on your terminal

What you see is called graphiql; an in browser IDEA which lets you explore a GraphQL API. On the left hand side is where you write the query that you would like to execute, the middle is where your results will appear and on the right is a documentation that allows you to see the available fields to query.

On the query side, clear everything and copy paste the below query and click the play button at the top;

{
People {
name
gender
vehicles
films
species
starships
}
}

You should see the below data on the results pane.

{
"data": {
"People": [
{
"name": "Luke Skywalker",
"gender": "male",
"vehicles": [
"https://swapi.co/api/vehicles/14/",
"https://swapi.co/api/vehicles/30/"
],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/",
"https://swapi.co/api/films/7/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": [
"https://swapi.co/api/starships/12/",
"https://swapi.co/api/starships/22/"
]
},
{
"name": "C-3PO",
"gender": "n/a",
"vehicles": [],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/5/",
"https://swapi.co/api/films/4/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/2/"
],
"starships": []
},
{
"name": "R2-D2",
"gender": "n/a",
"vehicles": [],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/5/",
"https://swapi.co/api/films/4/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/",
"https://swapi.co/api/films/7/"
],
"species": [
"https://swapi.co/api/species/2/"
],
"starships": []
},
{
"name": "Darth Vader",
"gender": "male",
"vehicles": [],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": [
"https://swapi.co/api/starships/13/"
]
},
{
"name": "Leia Organa",
"gender": "female",
"vehicles": [
"https://swapi.co/api/vehicles/30/"
],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/",
"https://swapi.co/api/films/7/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": []
},
{
"name": "Owen Lars",
"gender": "male",
"vehicles": [],
"films": [
"https://swapi.co/api/films/5/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": []
},
{
"name": "Beru Whitesun lars",
"gender": "female",
"vehicles": [],
"films": [
"https://swapi.co/api/films/5/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": []
},
{
"name": "R5-D4",
"gender": "n/a",
"vehicles": [],
"films": [
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/2/"
],
"starships": []
},
{
"name": "Biggs Darklighter",
"gender": "male",
"vehicles": [],
"films": [
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": [
"https://swapi.co/api/starships/12/"
]
},
{
"name": "Obi-Wan Kenobi",
"gender": "male",
"vehicles": [
"https://swapi.co/api/vehicles/38/"
],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/5/",
"https://swapi.co/api/films/4/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": [
"https://swapi.co/api/starships/48/",
"https://swapi.co/api/starships/59/",
"https://swapi.co/api/starships/64/",
"https://swapi.co/api/starships/65/",
"https://swapi.co/api/starships/74/"
]
}
]
}
}

That feels satisfying right! Alright, we have another query of a specific person which we can get by running the below query;

{
Person(id:"1"){
name
gender
vehicles
films
species
starships
}
}

As you can see from the query above, we are passing an id parameter of 1. The above should give you the below results;

{
"data": {
"Person": {
"name": "Luke Skywalker",
"gender": "male",
"vehicles": [
"https://swapi.co/api/vehicles/14/",
"https://swapi.co/api/vehicles/30/"
],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/6/",
"https://swapi.co/api/films/3/",
"https://swapi.co/api/films/1/",
"https://swapi.co/api/films/7/"
],
"species": [
"https://swapi.co/api/species/1/"
],
"starships": [
"https://swapi.co/api/starships/12/",
"https://swapi.co/api/starships/22/"
]
}
}
}

Unlike our first query which returns an array of People, this one returns a specific person.

Conclusion

At this point we have created a GraphQL API using an existing REST API without changing its underlying code or infrastructure. I hope you have gotten a basic idea of how you can start using GraphQL with the least investment and risk possible. Have a look at the code and see how you can adopt and implement this pattern on your own API’s and extend it even further by adding more functionality.

We have only used theQuery operation on this example but graphQL offers two more operations;

  • Mutations: For Creating Updating and Deleting data
  • Subscriptions: For creating and maintaining realtime connection to the server.

There is also a new advanced pattern called schema stitching which comes in handy if you are using a Micro Service based architecture with multiple GraphQL based API’s. You can create an API gateway that aggregates all of then in one place using schema stitching.

If you have any questions, observations or have some ideas, use the comments section to share them.

Connect with me Twitter |Github

--

--

Joe Ng'ethe

Software Engineer: Javascript, React, graphQL, UI’s. Follow me on Twitter @africansinatra