GraphQL vs REST

Post on 16-Apr-2017

435 views 1 download

Transcript of GraphQL vs REST

GraphQL vs RESTMaximilianos GJ Panas

Software Engineer@AgileActors@mgjp_

Stelios CharmpalisSoftware Engineer@AgileActors

@SteliosHarb

AgileActors Blog

REpresentational State TransferHTTP verbs(GET, POST, PUT, DELETE)Resource Based URLs - Endpoints (/ᴀ各lms/24)

REST(ful) API

 22. GET /characters/34  23. {  24.   "id": 34,  25.   "name": "Luke Skywalker", 26.   "birthYear": "1",  27.   "eyeColor": "blue",  28.   "gender": "male",  29.   "hairColor": "blond",  30.   "height": 172,  31.   "mass": 77,  32.   "skinColor": "fair"  33. }  34.   35.  

 18.   [  19.     "/characters/34",  20.     "/characters/35"  21.   ] 

 36.   37.   38.   39.   40.  

Retrieves the info about the `characters` with ID `34`

It is a period of civil war....

GET /films/1

{   "id": 1,   "title": "A New Hope",   "episodeID": 4,   "openingCrawl": "It is a period...",   "poster": "http://...",   "releaseDate": "2002‐05‐16",   "created": "2014‐12‐20T10:57:57.886Z",   "edited": "2014‐12‐20T20:18:48.516Z" }

PM (Project Manager)

Film Card using a RESTful API

A New HopeEpisode 4

It is a period of civil war....

Characters

{   "id": 1   "title": "A New Hope",   ... }

# 4 different queries 1. GET /films/1 2. GET /films/1/characters 3. GET /character/34 4. GET /character/35

# 1 Request ‐ Add boolean query string GET /films/1?include_character_details=true

# 1 Request ‐ New custom endpoint GET /films_with_character_details/1

Film Card using a RESTful API

A New HopeEpisode 4

Luke Skywalker

C­3PO

/* JSON Response */ {   "id": 1,   "title": "A New Hope",   "episodeID": 4,   "openingCrawl": "It is a period...",   "poster": "http://...",   "releaseDate": "2002‐05‐16",   "created": "2014‐12‐20T10:57:57.886Z",   "edited": "2014‐12‐20T20:18:48.516Z",   "characters": [     {       "id": 35,       "name": "C‐3PO",       "birthYear": "112BBY",       "eyeColor": "yellow",       "gender": "n/a",       "hairColor": "n/a",       "height": 167,       "mass": 75,       "skinColor": "gold",       "avatar": "http://..."     }, {     ...   }] } 

/* JSON Response */ {   "title": "A New Hope",   "episodeID": 4,   "openingCrawl": "It is a period...",   "poster": "http://...",   "characters": [     {       "name": "C‐3PO",       "avatar": "http://..."     }, {     ...   }] }

SIMPLIFY JSON RESPONSE

/* GraphQL Request */ {   title   episodeID   openingCrawl   poster   characters {     name     avatar   } }

/* JSON Response */ {   "title": "A New Hope",   "episodeID": 4,   "openingCrawl": "It is a period...",   "poster": "http://...",   "characters": [     {       "name": "C‐3PO",       "avatar": "http://..."     }, {     ...   }] }

A GRAPHQL REQUEST

Eliminate Overfetching

Eliminate Underfetching

Be Declarative

Increase Product Developer Autonomy

Natively Support Versioning

CORE GOALS

HELLO WORLD

{   bestFilm {     title   } }

{   "bestFilm": {     "title": "The Empire Strikes Back"   } }

ARGUMENTS

{   film(id: 1) {     title   } }

{   "film": {     "title": "A New Hope"   } }

COMPLEX QUERIES

{   film(id: 1) {     title     poster {       width       height       url     }   } }

{   "film": {     "title": "A New Hope",     "poster": {       "width": 300,       "height": 300,       "url": "https://..."     }   } }

NODES WITHIN NODES

{   film(id: 1) {     title     poster(size: 1000) {       width       height       url     }   } }

{   "film": {     "title": "A New Hope",     "poster": {       "width": 1000,       "height": 1000,       "url": "https://..."     }   } }

ALIASES

{   film(id: 1) {     title     regularPic: poster(size: 500) {       width       height       url     }     retinaPic: poster(size: 1000) {       width       height       url     }   } }

{   "film": {     "title": "A New Hope",     "normalPic": {       "width": 500,       "height": 500,       "url": "https://..."     },     "retinaPic": {       "width": 1000,       "height": 1000,       "url": "https://..."     }   } }

NESTED QUERIES

{   film(id: 1) {     title     characters {       name       films {         title         characters {           name         }       }     }   } }

{   "film": {     "title": "A New Hope",     "characters": [{       "name": "Yoda"       "films": [{         "title": "The Empire Strikes Back",         "characters": [{           "name": "Luke Skywalker"         }, {           "name": "Han Solo"         }]       }, {         "title": "Return of the Jedi",         "characters": [{           "name": "C‐3PO"         }, {           ...         }]       }] 

    }, { 

HOW GRAPHQLWORKS

User-Deᴀ各ned type system - "schema"

Data Universe is deᴀ各ned and connected on the server

Multiple Back-end services exposed through a singlecontrolled API

The client requests for exactly what it wants

TYPE SYSTEM (SCHEMA)

type Root {   bestFilm: Film   film(id: Int!): Film } 

type Film {   title: String   poster(size: Int = 300): Picture   characters: [Person] }

type Person {   name: String   films: [Film] } 

type Picture {   width: Int   height: Int   url: String }

GRAPHQL-JS

const Root = new GraphQLObjectType({   name: 'Root',   description: 'The starting point of your GraphQL query',   fields: () => ({     bestFilm: {       type: Film,       resolve: (root, args, context) => api.getTop('film')         .then(id => api.getFilm(id)),     },     film: {       type: Film,       args: { id: { type: new GraphQLNonNull(GraphQLInt) } },       resolve: (root, args, context) => api.getFilm(args.id),     },   }), });

Demo with GraphiQL

GraphQL is not bound by any client frameworkWays of using it on the client

Relay (Speciᴀ各cally for React)Lokka (Simplest lib, can be used with anything)Others (Apollo, XHR, etc.)

Queries can easily be broken apart andmerged togetheragainDeclare exactly what your data requirements are on thecomponent layer

THE CLIENT STORY

GraphQL is a speciᴀ各cation of a communication protocol, not a storagesystem, not a library

GraphQL is not tied to a speciᴀ各c language or framework

GraphQL does not allow clients to arbitrarily query your database(s)

GraphQL does not require a speciᴀ各c backend storage system

Security: Authentication is handled the same way as in REST

POSSIBLE MISCONCEPTIONS

Handling Resource intensive Queries on the Backend- facebook/Dataloader

Handling errors in resolvers- khadira/graphql-errors

Granular Control on querying- @defer, @async, @stream

Live Queries- Subscriptions

PRACTICAL PROBLEMS

THANK YOU!Any questions?