From GraphQL APIs to Supergraph Using Gloo Gateway Schema Stitching
May 23, 2024
Adam Sayah
In today’s business world, companies often have different teams or lines of business that necessitate multiple GraphQL APIs tailored to their needs. This approach helps teams work efficiently and deliver better user experiences, but there are instances where these schemas need to be merged into a unified API, enabling teams to access data from various sources through a single endpoint.
In the following tutorial we will discuss how we can merge multiple graphQL APIs with Gloo Gateway using GraphQL schema stitching.
What Is GraphQL Schema Stitching
GraphQL schema stitching is a technique in GraphQL that enables the merging of multiple schemas to create a unified supergraph. For instance, a company with an existing GraphQL API can use this method to enhance its current API by integrating it with a new GraphQL API developed using Gloo Gateway.
Real-World Example
Prerequisites
This tutorial uses Gloo Gateway Enterprise with GraphQL capabilities. If you need a trial key, reach out to us here.
Install Gloo Gateway Enterprise on your cluster using the following helm chart:
Assuming we have the following blog application, it consists of two microservices, one storing blogs and one storing the comments related to the blogs.
You can deploy these two services locally using the following command:
We can now use Gloo Gateway to create a GraphQL API that will aggregate the results of the two microservices. Let’s call the new GraphQL API the content API – it will return blogs and their related comments, and the usernames of the authors.
To do this in Gloo Gateway we will create some configuration. To start, we will create the GraphQL schema, which contains the resolvers:
apiVersion: graphql.gloo.solo.io/v1beta1
kind: GraphQLApi
metadata:
name: blogs-graphql
namespace: gloo-system
spec:
options:
logSensitiveInfo: true
executableSchema:
executor:
local:
enableIntrospection: true
resolutions:
getBlogs:
restResolver:
request:
headers:
:method: GET
:path: /blogs
upstreamRef:
name: default-blogs-80
namespace: gloo-system
getComments:
restResolver:
request:
headers:
:method: GET
:path: /comments?blogid={$parent.id}
upstreamRef:
name: default-comments-80
namespace: gloo-system
schemaDefinition: |
type Query {
"""Description of a blogs in HTML"""
getBlogs: [Blog] @resolve(name: "getBlogs")
}
type Blog {
id: Int
user: User
content: String
title: String
comments: [Comment] @resolve(name: "getComments")
}
type Comment {
id: Int
user: User
comment: String
}
type User {
username: String
}
Let’s understand the configuration above – we create a GraphQLApi custom resource in our Kubernetes cluster. The GraphQLApi contains two resolvers, getBlogs and getComments, getBlogs gets the blogs from the blogs service, getComments is then invoked to get all the comments related to a blog passing the blogId in a query parameter.
Now, to expose the GraphQL API to the public using the virtual service, create the following configuration:
Now your GraphQL API is exposed, and you can send your requests. For example, let’s retrieve the blogs and their related comments using the following query:
query MyQuery {
getBlogs {
comments {
comment
id
user {
username
}
}
content
id
title
user {
username
}
}
}
You should get a result like this:
{
"data": {
"getBlogs": [
{
"id": 1,
"title": "Proin eu mi",
"content": "Proin eu mi. Nulla ac enim. In tempor...",
"user": {
"username": "dbosnell2"
},
"comments": [
{
"id": 1,
"comment": "Fusce consequat. Nulla nisl. Nunc nisl...",
"user": {
"username": "cguillot21"
}
},
{
"id": 13,
"comment": "Vestibulum ac est lacinia nisi venenatis...",
"user": {
"username": "ballonby2a"
}
},
{
"id": 16,
"comment": "In sagittis dui vel nisl....",
"user": {
"username": "baguilar27"
}
}
]
}
]
}
}
This result can be used now to build an UI, for example, that lists new blogs and their related content. However, what if I want to display more information regarding the authors (of the blogs and comments), but I only have the usernames? Fortunately, in this example, there is another team that owns user data, and they have an existing GraphQL API that we can leverage to get more info regarding the authors.
Using schema stitching, it is possible to enhance the existing data from the GraphQL API created previously with user info fetched from an existing GraphQL API. The userInfo GraphQL API in this example is using an Apollo GraphQL server, but this GraphQL API can be served by any GraphQL server, it can also be another Gloo Gateway instance like in a tiered Gateway Deployment.
Now it is possible to retrieve the first and last name of a user using their username. This is possible because of the GraphQL schema stitching:
To stitch the two schemas we are going to do two things: first we will create a GraphQLApi that represents the User GraphQL API. In this case we want a remote execution of the graphQL API (proxied to the Apollo GraphQL server) and then we will create an GraphQLApi that represents the schema stitching.
Apply the following configuration to represent the proxied User GraphQL API:
apiVersion: graphql.gloo.solo.io/v1beta1
kind: GraphQLApi
metadata:
name: stitched-gql
namespace: gloo-system
spec:
options:
logSensitiveInfo: true
stitchedSchema:
subschemas:
- name: remote-graphql-users
namespace: gloo-system
typeMerge:
User:
# The selectionSet declares that the username from the Blogs service will be used as the key
# to fetch the user details from the Users service.
selectionSet: '{ username }'
queryName: getUserDetails
args:
username: username
- name: blogs-graphql
namespace: gloo-system
It is important to note that in the stitched GraphQL API we defined a typeMerge for the type User; this will invoke the query getUserDetails based on a username during the merge.
Finally, expose this new stitched GraphQL schema using a virtual Service; we will just update the existing one:
You can try the stitched GraphQL API now making the following query:
query MyQuery {
getBlogs {
comments {
comment
id
user {
username
firstname
lastname
}
}
content
id
title
user {
username
firstname
lastname
}
}
}
You should get the following response:
{
"comments": [
{
"comment": "Fusce consequat. Nulla nisl. Nunc nisl.\n\nDuis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.",
"id": 1,
"user": {
"username": "cguillot21",
"firstname": "Correy",
"lastname": "Guillot"
}
},
{
"comment": "Vestibulum ac ....",
"id": 13,
"user": {
"username": "ballonby2a",
"firstname": "Bendite",
"lastname": "Allonby"
}
},
{
"comment": "In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.",
"id": 16,
"user": {
"username": "baguilar27",
"firstname": "Braden",
"lastname": "Aguilar"
}
}
],
"content": "Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.",
"id": 1,
"title": "Proin eu mi",
"user": {
"username": "dbosnell2",
"firstname": "Dalia",
"lastname": "Bosnell"
}
},
Now we see that we get the first and last name of each author, and this was possible because of GraphQL schema stitching.
Use Gloo Gateway for GraphQL Stitching
In this blog, we looked at how GraphQL Schema Stitching can combine two GraphQL APIs using Gloo Gateway. One API was built with Gloo Gateway, and the other with Apollo, merging them seamlessly. This merging creates a “supergraph,” allowing access to data from different parts of an organization.
Gloo Gateway not only creates GraphQL APIs but also secures and monitors them with advanced gateway features. To see how GraphQL Schema Stitching can benefit your setup, request a Gloo Gateway trial key today.