Achieve Compliance, Zero Trust with Istio Ambient Mesh

READ THE WHITE PAPER

GraphQL tutorial

Learn to use fields, fragments, mutations, and more

Series: GraphQL

What is GraphQL?

GraphQL is a server-side runtime and query language for APIs that focuses on providing clients with the data they requested and nothing more. Designed to make APIs developer-friendly, fast, and flexible, GraphQL can be deployed within a unique integrated development environment (IDE) called GraphiQL. 

GraphQL offers an alternative to REST that allows developers to construct requests that pull data from several data sources within one API call. It enables API maintainers to flexibly deprecate or add fields without affecting existing queries. You can use it to build APIs with various methods, letting the GraphQL specification ensure the APIs function predictably.

Introduction to GraphQL

You can create a GraphQL service by defining types and fields based on those types, then creating functions for each field on each type. 

Here is an example in which a GraphQL service returns the logged in user and that user’s name:

type Query {
  Identity: User
}

type User {
  id: ID
  name: String
}

Features for each field in every type:

function Query_Identity(request) {
  return request.auth.user;
}

function Name_of_user(user) {
  return user.getName();
}

A GraphQL service is fully operational; it can start receiving GraphQL queries to process. This service ensures that a query only uses the stated types and fields before executing the given functions to return a response. Here’s an example of a query:

{
  Identity {
    name
  }
}

The JSON result will be:

{
  "Identity ": {
    "name": "Susan Lucas"
  }
}

GraphQL queries and mutations tutorial

This section shows how GraphQL querying works.

Fields

GraphQL focuses on querying object fields. First, let’s analyze a query and its output:

hero {
name
  }
}

 

{
  "data": {
"hero": {
   "name": "R2-D2"
}
  }
}

The query and result are identical. This is vital for GraphQL, because the goal is for clients to always receive the expected response, and for the server to know exactly which information the client is requesting. For example, R2-D2 is the string type returned by the field name. 

Fields can belong to objects and strings. Unlike a standard REST structure, GraphQL queries can traverse linked objects and associated fields, allowing clients to retrieve relevant data for each request.

{
  hero {
    name
    friends {
      name
    }
  }
}

{
  "data": {
    "hero": {
      "name": "R2-D2",
      "friends": [
        {
          "name": "Susan Lucas"
        },
        {
          "name": "Avril Luke"
        },
        {
          "name": "Justin Tom"
        }
      ]
    }
  }
}

 

Arguments

GraphQL lets you traverse objects with fields. However, passing parameters to fields is more efficient.

{
  human(id: "1015") {
    name
    height
  }
}

 

{
  "data": {
    "human": {
      "name": "Susan Lucas",
      "height": 1.68
    }
  }

Requests in a RESTful architecture can only include a single group of arguments consisting of query parameters and URI fragments. GraphQL replaces numerous API fetches since all fields with a nested object can have their parameters. Pass parameters into scalar fields to perform data modifications on the server rather than on each client.

{
  human(id: "1015") {
    name
    height(unit: FOOT)
  }
}

 

{
  "data": {
    "human": {
      "name": "Susan Lucas",
      "height": 5.511811
    }
  }
}

Many forms of arguments exist. As seen above, enumeration types represent several alternatives (in our case, FOOT). GraphQL has a default set of forms. However, a server can define additional types if they can be serialized in the transport structure.

Fragments

Consider an app that displays superheroes and their friends. This type of query could be complex, because of the need to repeat the fields for each side of the comparison. To solve this, GraphQL uses fragments. It enables the construction of sets of fields, which may then be incorporated into queries as necessary. The following example uses fragments to address the scenario described above:

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }

}

 

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}

 

{
  "data": {
    "leftComparison": {
      "name": "Susan Lucas",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {"name": "Avril Luke"},
        {"name": "Justin Tom"},
        {"name": "C-3PO"},
        {"name": "R2-D2"}
      ]
    },
    "rightComparison": {
      "name": "R2-D2",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {"name": "Susan Lucas"},
        {"name": "Avril Luke"},
        {"name": "Justin Tom"}
      ]
    }
  }
}

Repeating fields would make the above query monotonous. When you need to merge many UI components with distinct fragments as one primary data retrieve, fragments are used to break down complex application data specifications.

Variables

Your arguments should be written in the query string before this point. However, most apps will provide dynamic parameters to fields, such as a dropdown menu from which to choose the movie in a query, a search bar, or a collection of filters. 

The client-side code would have to automatically alter the query string at execution and serialize this into a GraphQL-specific structure if these dynamic parameters were passed in the query string. Instead, GraphQL’s built-in mechanism for passing dynamic data as a different dictionary makes this unnecessary. Instead, they refer to these numbers as variables.

Using variables requires three steps. First, change the query’s static variable to $variableName. Include $variableName in your query’s list of allowed variables. Lastly, send the name and value of a transport-specific variable in a different dictionary. The following output is as follows:

query HeroNameAndFriends($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}

{
  "episode": "JEDI"
}

{
  "data": {
    "hero": {
      "name": "R2-D2",
      "friends": [
        {"name": "Susan Lucas"},
        {"name": "Avril Luke"},
        {"name": "Justin Tom"}
      ]
    }
  }
}

When constructing queries in client code, you don’t need to start from scratch. You should never use string substitution to build queries with user-supplied values. Therefore this is also advisable for indicating which parameters in our query are meant to be dynamic.

Mutations

The ability to update data on the server is sometimes overlooked in discussions of GraphQL’s use. Because of the potential for negative impacts in RESTful interactions, it is generally accepted practice to avoid making changes to data via GET queries. Similarly, any conceivable query in GraphQL might be implemented to trigger a data update. 

 

Ensure that any operation that triggers a write is transmitted explicitly through a mutation. When doing a query, you can request nested fields if the mutated field produces an object. When an object is updated, the user can retrieve its current state. Consider the following mutation example:

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) 
{
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

{
  "ep": "JEDI",
  "review": {
    "stars": 4.5,
    "commentary": "This is an incredible movie!"
  }
}

{
  "data": {
    "createReview": {
      "stars": 4,
      "commentary": "This is an incredible movie!"
    }
  }
}

Enabling GraphQL with Solo.io Gloo GraphQL

The Gloo GraphQL module embeds a GraphQL server natively into Gloo Mesh and Gloo Gateway, enabling federated GraphQL queries of your APIs using your service mesh and API gateways. No additional GraphQL servers required!

Combine the developer-friendly GraphQL query language for APIs with Istio’s ability to secure, manage, and observe application traffic across microservices. This eliminates the need for a distinct system of servers and schema libraries of parsers and resolvers for GraphQL; all of your policies and requests can be managed in Envoy Proxy filters. Leveraging the existing capabilities Solo provides via Envoy, you can scale from single, monolithic GraphQL APIs to a federated graph spanning multiple clusters.

Get started with GraphQL on Gloo GraphQL today.

Sections