The most straightforward way to interact with a GraphQL API is to make an HTTP POST request to a GraphQL server, for example using JavaScript's fetch:
require('isomorphic-fetch');
const query = `
query {
posts {
title
}
}
`;
fetch('https://1jzxrj179.lp.gql.zone/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
})
.then(res => res.json())
.then(res => console.log(res.data));
GraphQL bindings provide a convenient interface for interacting with a GraphQL API with your favorite programming language. Instead of sending queries as strings like we demonstrated above, you can invoke a binding function which constructs a GraphQL request and sends it to a GraphQL server for you.
Bindings can be useful in combination with statically typed languages that IDEs and code editors to leverage tooling that can be configured in such a way that they validate GraphQL requests at compile time or even provide auto-completion for an advanced developer experience.
A perspective that onboards engineers is to think of GraphQL bindings as an auto-generated SDK for GraphQL APIs.
- Accessing GraphQL APIs from a script
- GraphQL-based service-to-Service communication
- Building GraphQL gateways
- Composing/Sharing GraphQL APIs as modular building blocks
- Implementing a custom GraphQL API on top of Prisma
- Implementing custom operations for an existing GraphQL API
Assume the following GraphQL schema is deployed to a GraphQL server on the web:
type User {
id: ID!
name: String
}
type Query {
users: [User!]!
}
type Mutation {
createUser(name: String!): User!
}
The server's API accepts two operations:
- A query to retrieve all
User
s - A mutation to create a new
User
Now install the package graphql-binding-example
through NPM or yarn:
yarn add graphql-binding-example
# or
npm install graphql-binding-example
You can find code for the
graphql-binding-example
here. Learn how to create your own GraphQL binding here.
In the following, we'll discuss three scenarios illustrating how the example binding can be used.
Inside a Node script, you could install the graphql-binding-example
via npm
or yarn
and then use it inside the script:
In this example, createUser
takes two arguments:
- The arguments for the mutation
- The selection set of the mutation
The invocation of the createUser
binding function therefore constructs and sends the following mutation to the GraphQL server:
mutation {
createUser(name: "Alice") {
id
}
}
Similarly, you could write script that sends the users
query via the invocation of a binding function:
This time, no arguments are being passed and the selection set asks for the id
and the name
of the User
s being returned.
The binding function therefore constructs and sends the following query to the GraphQL server:
query {
users {
id
name
}
}
When responding to webhooks from 3rd party services, bindings are useful to access your GraphQL API to do specific work.
For this example, consider an application which responds to webhooks from a service that has its own user accounts system. In this service, the system sends a HTTP POST
whenever a new user is created and we want to add that user to our database.
To test out a webhook against this Glitch example you can run the following:
curl -d '{"name": "Andy"}' -H "Content-Type: application/json" -X POST https://holy-shad.glitch.me/users/created
An example response from running this command is below:
The ID of the created user is: cjkpu8tboo6b00b77sdbnaii5 and the name is Andy
When building gateways for GraphQL-based microservices, bindings are especially helpful. In the previous example, we have demonstrated the API where the selection set for the constructed query is passed as a string. For this use case, the binding API allows to pass on the info
argument of GraphQL resolvers.
For this example, consider the graphql-binding-example
binding representing the SDK of a GraphQL microservice and assume you are now building a GraphQL gateway layer on top of it to adjust the functionality. Let's say we want to generate a User
from an allowed list of names:
This means the gateway layer will have the following schema:
type User {
id: ID!
name: String
}
type Query {
user(id: ID!): User
}
type Mutation {
createUserWithAllowedName: User!
}
Now, when implementing the resolvers for this schema, you're going to delegate the queries to the underlying GraphQL microservice - using the binding instance from the 'graphql-binding-example'
package.
Play around with the hosted playground to see the binding in action!
For the user
and createUserWithAllowedName
resolvers, the binding will behave exactly like in the previous example and construct a GraphQL query/mutation to send to the API.
The big difference to the previous example with the simple Node script is that now the selection set is not hardcoded any more. Instead, it is provided through the info
object of the incoming query/mutation. The info
object carries the abstract syntax tree (AST) of the incoming GraphQL query, meaning it knows the requested fields as well as any arguments and can simply pass them along to the underlying GraphQL API - this is called query delegation.
To learn more about the
info
object, check out this deep-dive article into its structure as well as its role during the query resolution process.