0% found this document useful (0 votes)
90 views

Graphql Essentials: Declarative Data Fetching Over A Single Api

Refcard GraphqQL-Essentials
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
90 views

Graphql Essentials: Declarative Data Fetching Over A Single Api

Refcard GraphqQL-Essentials
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

BROUGHT TO YOU IN PARTNERSHIP WITH

CONTENTS

GraphQL Essentials
∙ The Evolution of GraphQL

∙ The Fundamentals of GraphQL

∙ Design Principals

∙ Schemas and Types

Declarative Data Fetching Over ∙ GraphQL Queries and Mutations

a Single API ∙ Fields, Arguments, Variables,


Fragments, Subscriptions, and
Directives

∙ Securing Your GraphQL APIs

∙ Additional Resources

VISHWA RATNA
SOFTWARE ENGINEER, SYNPULSE MANAGEMENT CONSULTING

GraphQL is a language-independent specification for client-server


GraphQL eliminates the need for versioning by
communication. It is declarative (i.e., empowers developers to
Versionless API deprecating APIs on a field level. Aging fields
specify what needs to be fetched rather than how) and also serves as evolution can be later removed from the schema without
a runtime or fulfilling queries with your data. impacting the existing queries.

Fragments can be visualized as functions in


THE EVOLUTION OF GRAPHQL Shared query logic programming languages. A GraphQL Fragment is
In 2012, Facebook decided to revamp its native mobile apps as those (Fragment) a reusable unit of a GraphQL query, which creates
for iOS and Android were just thin wrappers around the views of the a shared piece of query logic.

mobile website and often crashed by multiple REST calls. This was a
Over-fetching and
solution to overcome the disadvantages of REST, which paved a way GraphQL lets the front end fetch only the data
under-fetching
needed.
to the birth of what we know as GraphQL. Today, GraphQL powers problems resolved
almost all of Facebook’s data fetching and is used in production by
organizations such as IBM, Intuit, GitHub, and Airbnb.

BENEFITS OF GRAPHQL

BENEFIT DESCRIPTION

Suitable for GraphQL unifies multiple systems behind a


complex systems single API, thus encapsulating the complexity of
and microservices each system.

GraphQL is typically served over HTTP via a


Data fetching with
single endpoint that expresses the full set of
a single API call
capabilities of the service.

The GraphQL API is tightly coupled with code,


Autogenerating API
so once a field, type, or query changes, so do
documentation
the docs.

TABLE CONTINUES IN NEXT COLUMN

1
REFCARD | GRAPHQL ESSENTIALS

FUNDAMENTALS OF GRAPHQL
An entry point into a type Query {
DESIGN PRINCIPLES GraphQL service moviesByTitle(title:

GraphQL offers some guidelines for how to think about a service: Query types The Query type defines the String!, limit: Int=
queries available for the 3): [Movie]
GraphQL service. }
PRINCIPLE DESCRIPTION

GraphQL is driven by the data needs of the client, the type Mutation {
Product-centric Also an entry point into the
language, and the runtime that support the client. reviewMovie(review:
Mutation GraphQL service
ReviewInput):User-
types Mutations are update Review
Client-specific A GraphQL server provides the capabilities that
operations. }
queries clients can consume.

A GraphQL server is backed by the GraphQL type enum RATING {


Strong typing system. In the schema, each field has a specific type G
A type of scalar restricted
against which it will be validated. Enumeration PG
to a set of pre-defined
types PG13
values
A GraphQL schema is hierarchical — i.e., fields are R

nested within other fields, and the query is shaped }


Hierarchical
like the data that it returns.
Abstract type that includes
The client can query the GraphQL server’s a set of fields that must
Introspective
type system. be implemented by interface Person {
Interface another type id: ID!
types Interface types are name: String
SCHEMAS AND TYPES }
used when returning an
In GraphQL, a schema is used to define a collection of types and object that can be one
the relationships between them. The GraphQL server uses a of several types.

schema to define and describe the shape of the data graph. The
schema establishes the hierarchy of types with fields, exposing the input ReviewInput {
Used to pass complex rating: Int!
functionality available for the client applications to use. movieId: ID!
Input types objects to a mutation
or query userId: ID!
The GraphQL schema language, also called the GraphQL Interface }
Description Language (IDL), is used to define a schema and types.
Similar to interface types
TYPE DESCRIPTION EXAMPLE union PersonResult =
Union types However, Union types do User | Actor
not specify common fields.
type Movie {
id: ID!
An object type that can be
title: String
fetched, including the fields
it provides year: Int
GRAPHQL QUERIES AND MUTATIONS
plot: String
For example, Movie is poster: String Queries and mutations are the entry point to the GraphQL service.
an object type with fields genres: [String]
Object types
title, year, genres, similar: [Movie] FIELDS
and plot. [Movie] rating: RATING Each type is composed of one or more fields, which can be scalar
indicates an array of actors: [Actor]
values or complex objects that refer to other types, resulting in
Movie objects, and ! series: [Series]
indicates a required field. avgStars: Float nesting. All GraphQL queries must at least specify the fields to be
} returned. This is referred to as the selection set.

Common primitive types Consider the following schema:This is a code block

These are Int, Float, type Query {


Scalar types title: String
String, Boolean, ID topRatedMovies: [Movie]
(serialized as a string and }
can be human readable). type Movie {
id: ID!
TABLE CONTINUES IN NEXT COLUMN
CODE CONTINUES ON NEXT PAGE

3 BROUGHT TO YOU IN PARTNERSHIP WITH


REFCARD | GRAPHQL ESSENTIALS

title: String type Query {


year: Int moviesByTitle(title: String!, limit: Int = 3):
plot: String [Movie]
poster: String }
imdbRating: Float
genres: [String]
Query:
similar(limit: Int = 3): [Movie]
rating: RATING {

actors: [Actor] moviesByTitle(title: "Matrix Reloaded") {


avgStars: Float title
} similar(limit: 2) {
title
Query:his is a code block year
}
{
}
topRatedMovies {
}
title
year
Result:
avgStars
} {
} "data": {
"moviesByTitle": [
Result: {

{ "title": "Matrix Reloaded, The",

"data": { "similar": [

"topRatedMovies": [ {

{ "title": "Matrix, The",

"title": "Godfather, The", "year": 1999


"year": 1972, }

"avgStars": 4.4875 ]

}, }

{ ]
}
"title": "Shawshank Redemption, The",
}
"year": 1994,
"avgStars": 4.487138263665597
},
VARIABLES
{
"title": "On the Waterfront", You can use variables in a GraphQL query to avoid injection attacks
"year": 1954, by string interpolation to build queries from dynamic or user-
"avgStars": 4.448275862068966 supplied content. To use variables, first declare $varName as a
} valid variable for the query, then replace the value in the query with
]
$varName. Finally, pass the key-value pair varName: value in a
}
dictionary alongside the query.
}

For example:

ARGUMENTS query MoviesByTitle($movieTitle: String!,


You can also pass arguments to queries. Arguments can be required $similarLimit: Int) {
or optional. A default value is declared when using an optional moviesByTitle(title: $movieTitle) {
argument. There was an example of declaring an argument above the title

similar field in the Movie type, but the following also shows declaring similar(limit: $similarLimit) {

an argument (limit) to a query (moviesByTitle), as well as passing title

an argument to the similar field on the Movie type (see next column). year

CODE CONTINUES ON NEXT PAGE

4 BROUGHT TO YOU IN PARTNERSHIP WITH


REFCARD | GRAPHQL ESSENTIALS

} Mutation:
}
} mutation {
reviewMovie(userId: "20", movieId: "16", rating:
5) {
Query:
movie {
{ title
"movieTitle": "Matrix Reloaded", similar(limit: 2) {
"similarLimit": 2 title
} }
}
user {
Result:
name
{ }
"data": { rating
"moviesByTitle": [ }
{ }
"title": "Matrix Reloaded, The",
"similar": [ Result:
{
{
"title": "Matrix, The",
"data": {
"year": 1999
"reviewMovie": {
}
] "movie": {
} "title": "Casino",
]
"similar": [
}
} {
"title": "Four Brothers"
},
MUTATIONS {
While queries allow you to request data, GraphQL mutations are "title": "Night and the City"
}
used to update data and provide an additional entry point into
]
our GraphQL API. To use mutations, include a mutation type in the },
schema, which defines the mutations allowed. One way to think of "user": {
mutations is as functions that get executed in the GraphQL server. "name": "Nicole Ramsey"
},
Consider a UserReview type: "rating": 5
}
type UserReview { }
user: User }
rating: Int
movie: Movie
INPUT TYPES
}
In the previous mutation example, three individual arguments of

To create a new UserReview, define a mutation to perform this primitives were passed to define the intended update. Instead, an

update: input type can be used to pass a more complex object as a variable.
Input types are especially useful for mutations where the goal is to
type Mutation {
pass an update as a single object.
reviewMovie(userId: ID!, movieId: ID!, rating:
Int): UserReview
Input type:
}
input ReviewInput {
rating: Int!
Note that the mutation returns a UserReview object. This means
movieId: ID!
that you can access any of the fields available on Movie and User
userId: ID!
(in a nested fashion). }

5 BROUGHT TO YOU IN PARTNERSHIP WITH


REFCARD | GRAPHQL ESSENTIALS

Then modify the reviewMovie mutation to accept an argument of {


moviesByTitle(title: "Matrix Reloaded") {
type ReviewInput:
...movieSummaryFields
type Mutation { }
reviewMovie(review: ReviewInput!): UserReview }

} fragment movieSummaryFields on Movie {


title
year
Then the mutation becomes:
imdbRating
mutation CreateReviewForMovie($review: ReviewInput) }
{
reviewMovie(review: $review) { Result:
movie {
{
title
"data": {
}
"moviesByTitle": [
user {
{
name
"title": "Matrix Reloaded, The",
}
"year": 2003,
rating
"imdbRating": 7.2
}
} }
]
}
Variables: }

{
"review": {
INLINE FRAGMENTS
"movieId": "16",
"userId": "20", Inline fragments are useful for queries where we have to resolve the
"rating": 5 type at runtime. They are marked by the ...on <TYPE> syntax.
} They are primarily used when one of the abstract types (Union or
}
Interface) needs to be implemented in GraphQL.

Result: Consider the following:

{ type Query {
"data": { personByName(name: String!): [PersonResult]
"reviewMovie": { }
"movie": { union PersonResult = User | Actor
"title": "Casino"
}, PersonResult can be either a User or Actor. In this case, an
"user": { inline fragment must be used to ensure the query result is resolved to
"name": "Nicole Ramsey"
the correct type:
},
"rating": 5 {
} personByName(name: "Tom Cruise", limit: 3) {
} ... on Actor {
} name
movies {
title
FRAGMENTS }
A fragment is a reusable set of fields that can be defined and }
... on User {
referenced by name in a GraphQL query. Fragments allow you to
name
avoid repetition in queries by providing a way to reference this set of
}
fields by name. To apply a fragment inside a query, use a fragment }
spread operator (...) inside the selection set (see next column). }

6 BROUGHT TO YOU IN PARTNERSHIP WITH


REFCARD | GRAPHQL ESSENTIALS

Result: DIRECTIVES
A GraphQL directive allows for static and dynamic schema
{
"data": {
modification based on variables, which is similar to feature flags.
"personByName": [ Below is an example:
{
"name": "Tom Cruise", @skip @include
"movies": [
{ query query
"title": "Risky Business" myMovieQuery($testValue: myMovieQuery($testValue:
}, Boolean!) { Boolean!) {
{
experimentalField @ experimentalField @
"title": "Cocktail"
skip(if: $testValue) include(if: $testValue)
},
} }
{
"title": "Top Gun"
In this example, In this example,
}
experimentalField will experimentalField will
]
only be queried if the variable only be queried if the variable
}
$testValue has the value $testValue has the value
] true.
false.
}
}
Learn more about directives here.

SUBSCRIPTIONS
SECURING YOUR GRAPHQL APIS
Often, clients want to receive updates from the server when certain
Not securing your APIs properly can land you in serious trouble,
data changes. In addition to queries and mutations, GraphQL
especially with GraphQL. Since clients have the option to
supports a third operation, a subscription, which allows a client
craft complex queries, servers must be ready to handle them
to subscribe to receive event updates. Subscriptions are real-time
properly. They may be abusive or malicious queries, or they may
streaming chunks of data that allow bi-directional interaction over a
simply be very large. In both cases, the query can potentially
single Transmission Control Protocol (TCP) socket. Clients specify the
take down your GraphQL server.
data they want by sending a subscription query.
GraphQL recommends a few guidelines and strategies.
Let's say a client wants to receive updates when a user submits a
movie rating for a particular movie. If the user is viewing a movie
TIMEOUT
page, the UI would update when a new rating is received.
Setting Timeout informs a server and any intermediaries of the
maximum time that a client will await a response to its request.
Every time the underlying MovieReviewSubscription is changed,
For example, a server configured with a five-second timeout
the new value for rating is pushed over a web socket or some other
would stop the execution of any query that takes more than five
type of persistent connection. The nature of operations performed by
seconds to execute.
subscription is slightly different than that of query — the former
has real-time fetching of data while the latter just fetches once.
LIMITING MAXIMUM QUERY DEPTH
Subscription query: GraphQL schemas are often cyclic graphs, meaning a malicious
GraphQL query can be created to exploit nested relationships. For
subscription MovieReviewSubscription($movieId: ID!)
example, there is an Entertainment API that exposes an Actor
{
movieReviewSubscription(movieId: $movieId) { type. Each Actor can belong to a Movie, and each Movie can
movie { have an Actor in the form of an Artist. Considering this, a
title query could be formed, as shown on the following page.
}
rating
}
}

7 BROUGHT TO YOU IN PARTNERSHIP WITH


REFCARD | GRAPHQL ESSENTIALS

FIELD-BASED PERMISSIONS
Given a schema with the objects Users, Bookings, and Movies,
the Bookings and Users objects are private, so authentication
is needed to access them. Authentication is handled by resolvers.
The Movies object is public and can be accessed without being
authenticated. Now, what should happen with the query below if the
client is not authenticated?

A cyclical relationship could very well exist between the Actor and
Assuming that the client making the query above isn’t authenticated,
the Movie — for example, Johnny Depp (Actor) is in Pirates of the
they can access all of the user’s data, which breaches user privacy.
Caribbean (Movie), and he is also an Artist. This is a circular
The problem above is solved by adding a permission on the query,
reference that could lead to significant load on API servers.
object and field level. Permission on field level allows you to add a
Maximum depth-limiting caps the amount of nesting that can be check over the field.
present in any given request. Before the request is processed, its
Let’s say for the object User, some fields can be viewed by anyone
depth is calculated (the above query has six nesting levels). If the
like name, but we don’t want to show the field Booking, as this data
nesting depth exceeds the given limit, it is rejected outright.
is considered private and only accessible by the User or Admin.

QUERY COMPLEXITY LIMITS


Another troublesome query relates to complexity — for example,
a client can simply request many fields on the root query object:

Logic inside resolver:

To deal with this kind of query, GraphQL has built-in support for
complexity analysis. An arbitrary number can be assigned as points
to any field. When an incoming query is received, these arbitrary
numbers are summed. If the total exceeds the threshold, an When a field is restricted and used in a GraphQL operation, the
appropriate error message is returned. consumer receives an error response (e.g., 400 Bad Request).

8 BROUGHT TO YOU IN PARTNERSHIP WITH


REFCARD | GRAPHQL ESSENTIALS

CONCLUSION
While this Refcard covered the primary benefits of GraphQL and
WRITTEN BY VISHWA RATNA,
introduced some essential GraphQL concepts, as well as more SOFTWARE ENGINEER, SYNPULSE MANAGEMENT
advanced fundamentals, there are still many topics left to explore. CONSULTING

Below is an overview of additional resources available to learn Vishwa Ratna is a security researcher by
more about GraphQL and tools to simplify the process of building passion and a software engineer who specializes
in GraphQL and Blockchain. He is currently working with
GraphQL applications: Synpulse Management Consulting.

With a passion and interest in IT-Security, he has helped various


GraphiQL In-browser IDE for exploring GraphQL
IT firms mitigate severe vulnerabilities related to GraphQL. You
can find and connect with him online.
Opinionated structure for how to build a GraphQL
graphql-tools schema and resolvers in JavaScript, following
the GraphQL-first development workflow

Apollo Client Flexible GraphQL client for React and native apps.

Apollo
In-browser GraphQL server playground
Launchpad
DZone, a Devada Media Property, is the resource software developers,
engineers, and architects turn to time and again to learn new skills, solve
Prisma Open-source database toolkit software development problems, and share their expertise. Every day,
hundreds of thousands of developers come to DZone to read about the latest
technologies, methodologies, and best practices. That makes DZone the
Utility for batching and caching requests, often ideal place for developer marketers to build product and brand awareness
DataLoader and drive sales. DZone clients include some of the most innovative
used with GraphQL services
technology and tech-enabled companies in the world including Red Hat,
Cloud Elements, Sensu, and Sauce Labs.
Create a GraphQL API by reflection over a
PostGraphQL
PostgreSQL schema
Devada, Inc.
600 Park Offices Drive
Graphql.org Portal for all things GraphQL
Suite 150
Research Triangle Park, NC 27709
GraphQL A working draft of the GraphQL specification, 888.678.0399 919.678.0300
specification maintained by Facebook Copyright © 2020 Devada, Inc. All rights reserved. No part of this publication
may be reproduced, stored in a retrieval system, or transmitted, in any form
or by means of electronic, mechanical, photocopying, or otherwise, without
Awesome A collection of links to GraphQL resources prior written permission of the publisher.
GraphQL including tutorials, libraries, and examples

9 BROUGHT TO YOU IN PARTNERSHIP WITH

You might also like