Go API's: REST & GraphQL

John Machahuay Giraldo

About me

  • Full Stack developer
  • Originally a Web developer, now doing both web and mobile development
  • Now building an app for IOS and android with React Native
  • Speaker in meetups.

REST

 - REST (REpresentational State Transfer) 

 - Defined in 2000 by Roy Fielding, who was the main      coautor of the especification of HTTP.

 - HTTP Verbs

 - Resources based on URLS - endpoints
 - Resources are the information that you want to access, modify, delete independently of the format.

 - A representation is a machine readable explanation of the current state of a resource.

REST

/users/7/ 
getUserById(7) responds -> 
user: {
    "email": "johndoe@mailinator.com", 
    "username", "john doe"
}

/users/7/organizations
getOrganizationsByUser(7) responds -> 
organizations: {
    organizations: [
        {"name": "Org1"}, {"name": "Org2"}
    ]
}

then display a list of organizations based on the user

REST

  • Define and specify precisely the data you want adding many endpoints.
  • Expose a suite of URLs each of which expose a single resource.
  • Any change can be considered a breaking change, and breaking changes require a new version.
  • This has lead to a common practice of always avoiding breaking changes and serving a versionless API.
  • Postman for testing API REST.

GraphQL

GraphQL is a new way to think about building and querying APIs. Rather than construct several REST requests to fetch data that you're interested in, you can often make a single call to fetch the information you need.

GraphQL Query

  {
    user(id: 1564) {
      name,
      email
    }
  }

Sample response

{
  "data": {
    "user": {
      "name": "Dan",
      "email": "dan@company.com"
    }
  }
}

GraphQL

GraphQL is, above all, a querying language, and the format of the query you send matches the data you receive. For example, given the following query:

{
  viewer {
    login
    bio
    organizations(first: 3) {
      edges {
        org:node {
          name
        }
      }
    }
  }
}
{
  "data": {
    "viewer": {
      "login": "gjtorikian",
      "bio": "I inhale and exhale.",
      "organizations": {
        "edges": [
          {
            "org": {
              "name": "GitHub"
            }
          },
          {
            "org": {
              "name": "Atom"
            }
          }
        ]
      }
    }
  }
}

GraphQL Query

  {
    user(id: 1564) {
      name,
      email,
      friends {
        id,
        name
      }
    }
  }

Sample response

{
  "data": {
    "user": {
      "name": "Dan",
      "email": "dan@company.com",
      "friends": [
        {
          "id": 1056,
          "name": "Marie"
        },
        {
          "id": 1232,
          "name": "Bob"
        }
      ]
    }
  }
}

GraphQL Query

  {
    user(id: 1564) {
      name,
      email,
      friends {
        id
      }
    }
  }

Sample response

{
  "data": {
    "user": {
      "name": "Dan",
      "email": "dan@company.com",
      "friends": [
        {
          "id": 1056
        },
        {
          "id": 1232
        }
      ]
    }
  }
}

Client view

{
  user (id:1313) {
    name, email,
    portfolio: {
      id, description,
      items: {
        id, title
      }
    }
  }
}

Graphql query

How Graphql works

Backend

Client view

loadUserById
loadPortfolioById
loadItemsByPortfolioId
{
  user (id:1313) {
    name, email,
    portfolio: {
      id, description,
      items: {
        id, title
      }
    }
  }
}

Graphql query

How Graphql works

Backend

Client view

loadUserById
loadPortfolioById
loadItemsByPortfolioId
{
  user (id:1313) {
    name, email,
    portfolio: {
      id, description,
      items: {
        id, title
      }
    }
  }
}

Graphql query

How Graphql works

Backend

Mongo with users

SQL with portfolios

Whatever API

Client view

loadUserById
loadPortfolioById
loadItemsByPortfolioId
{
  user (id:1313) {
    name, email,
    portfolio: {
      id, description,
      items: {
        id, title
      }
    }
  }
}

Graphql query

How Graphql works

Backend

Mongo with users

SQL with portfolios

Whatever API

... it also can be  a "changing" query

Client view

loadUserById
loadPortfolioById
loadItemsByPortfolioId
{
  user (id:1313) {
    name, email,
    portfolio: {
      id, description,
      items: {
        id, title
      }
    }
  }
}
{
  data: {
    user: {
      name: 'John',
      email: 'john@doe.com',
      portfolio: {
        id: 33545232,
        description: 'Best portfolio...',
        items: [
          { id: 231232, title: 'first item' },
          { id: 545444, title: 'best website' }
        ]
      }
    }
  }
}  

Graphql query

JSON response

How Graphql works

Backend

GraphQL is:

- Declarative (client declares what he needs)

- Hierarchical (nestings...)

- Strongly-typed (int, string, array...)

- No data overfetching (and backward compatibility)

- Product-centric (client app is the product)

- Application-Layer Protocol (json, xml, http, sql, ...)

- Introspective (documentation = schema)

GraphQL vs REST

REST

GraphQL

is an approach

is a protocol

- is it RESTful or not?

- often "non-rest" decisions

- everyone feels guilty

What is?

REST

GraphQL

/contracts/123123
/contracts/123123/afterSales
/contracts/123123/documents
/contracts/123123/history

single query

Fetching complex objects

Fetching complex objects

REST

GraphQL

Typization

Weak

- Enum? Int or string?

- I thought there was an array,      but there was NULL!!

Strong

Array means Array

Enum means enum

REST

GraphQL

{
  "insuranceStart": "2016-01-15T00:00:00.0000000+01:00",
  "contractReferenceNumber": null,
  "calculatedTariff": {
    "pricingDetails": {
      "paymentPeriod": 4,
      "amount": 12.28982,
      "isInvoiceAllowed": null,
      "isCreditCheckRequired": null,
      "isSepaMandateAcceptanceRequired": null
    },
    "insurance": {
      "id": 273,
      "efeedbackProviderId": 215,
      "whiteLabelId": null,
      "name": "DMB Rechtsschutz",
      "description": "Securo",
      "logo": "/Resources/Images/Insurance/dmb.gif"
    },
    "tariffInfo": {
      "id": 997,
      "name": "Securo",
      "detailedFeatures": [
        {
          "id": 4,
          "groupId": 12,
          "groupName": "Allgemeine Leistungen",

769 more lines of JSON

/api/contracts/1890373

{
  contract (id: 1890373) {
    calculatedTariff {
      pricingDetails { paymentPeriod, amount }
    },
    insuredPerson {
      firstName, lastName, email
    }
  }
}
{
  "calculatedTariff": {
    "pricingDetails": {
      "paymentPeriod": 4,
      "amount": 12.28982,
    },
  },
  "insuredPerson": {
    "firstName": "Max",
    "lastName": "Pecu",
    "email": "andreas.freier@check24.de",
  }
}

Overfetching

REST

GraphQL

The focus?

Long-lived network-based applications that span multiple organizations

Dynamically evolving client-server applications. The api is consumed internally.

(that's exactly what we do!)

Lots of stuff...

Libraries: Javascript, Go, .NET, Java, Python etc...

More features: Interfaces, unions, enums, fragments, named queries, mutations

https://github.com/chentsulin/awesome-graphql#lib-go

Demo

REST

GraphQL

GraphQL

  • The ability to define and specify precisely the data you want for your integration
  • Served over HTTP via a single endpoint which expresses the full set of capabilities of the service.
  •  A GraphQL server operates on a single URL/endpoint, usually /graphql
  • Entities in GraphQL are not identified by URLs.
  •  Takes a strong opinion on avoiding versioning by providing the tools for the continuous evolution of a GraphQL schema.
  • New capabilities can be added via new types and new fields on those types without creating a breaking change.
  • GraphQL natively supports performing an introspection query
  • GraphiQL for testing API GraphQL.

Resources

Thanks

John Machahuay Giraldo

GraphQL vs REST

By johnprog

GraphQL vs REST

  • 1,494