Building a great API program takes time. You've probably made a large investment in REST, SOAP, and other HTTP-based APIs already. When a new HTTP-based protocol comes on the scene, your first reaction definitely isn't to rush out and try it. GraphQL is relatively new - only a decade old, and we're hearing of more developers who want to try it out but are loathe to leave their existing REST APIs behind. It's not just a case of swapping out your API. You must also refactor all your client applications that access that API at the same time.
Enter Synthetic GraphQL - a new feature of Azure API Management. Synthetic GraphQL allows you to build a GraphQL API from your existing HTTP-based APIs (including REST and SOAP). It allows your APIs to coexist while you migrate your client applications to GraphQL. You can then slowly migrate your existing APIs to a GraphQL service over time or as your needs evolve. You don't have to take the big bang approach to updating your APIs and client applications at the same time. In fact, you may not even want to have everything in a GraphQL service. You can also augment a GraphQL service with some information from another API, like Microsoft Graph or Dataverse. It's easy, for example, to store the user ID or email address of a user in GraphQL and then pull the other information you want to present in your client applications (like the users name or title) from Azure Active Directory via Microsoft Graph.
Most developers create a todo list application as part of their learning experience, so let's see how we can use such an API to create a GraphQL service. I have an existing todo list REST API that supplies a CRUD (create, read, update, delete) interface to the data:
I can model this interface in GraphQL:
type TodoItem {
id: ID!
title: String!
completed: Boolean!
}
input CreateTodoItemInput {
title: String!
}
input ReplaceTodoItemInput {
id: ID!
title: String!
completed: Boolean!
}
type Query {
todoItems: [TodoItem]
todoItem(id: ID!): TodoItem
}
type Mutation {
createTodoItem(input: CreateTodoItemInput!): TodoItem!
replaceTodoItem(input: ReplaceTodoItemInput!): TodoItem!
deleteTodoItem(id: ID!): Boolean
}
To create this GraphQL API within the Azure API Management service:
Once you have created the API, you will be taken to the Design tab of the GraphQL API. Since the GraphQL schema is central to the understanding of the API, we've made the schema the first tab you see.We've also added some features to the editor to make navigating large schemas easier. For example, you can search or go to a specific line. You can also right-click on any type and use Go to definition to scroll to where it is defined and Peek definition to look at the definition in line.
The next step is to create resolvers. Resolvers are how GraphQL requests are fulfilled. You can (and should) add resolvers for each query and mutation in your schema. In addition, you may want to add resolvers to fields or types elsewhere in the schema. For example, let's say you have a REST API that returns a list of IDs, and you have to make a further call to get the details of the type that the ID refers to. You can add a resolver to the type to gather the rest of the information that is needed to respond to the client.
You can add a resolver in two ways:
Whichever way you get to the resolver, you will be asked to create the resolver policy - an XML document that defines how to call the HTTP API and how to change the response to match the requirements of the GraphQL response. For example, the createTodoItem resolver uses the following policy:
<http-data-source>
<http-request>
<set-method>POST</set-method>
<set-url>{{todorestapi}}/api/todoitems</set-url>
<set-body>@(Context.GraphQL.Arguments["input"].ToString())</set-body>
</http-request>
</http-data-source>
This is a fairly basic resolver. I've used a named value (called todorestapi) to hold the base URL of my API, and I've converted what I received from the GraphQL request (as JSON) to be the (JSON) body of the request. You can also add authorization headers, select certificates, or do whatever else is needed to communicate with the REST API. What comes back from the REST API matches what I want to send back to the client. However, if it were different, I could add a <http-response> section to this policy and use <set-body> to set the response explicitly.
Now that I've created one resolver, I can easily create the others I need - one for each query and mutation.
It's common to have several resolvers that are similar to one another. They may only differ by the name of the API, for example. You can use the Clone feature from the Resolvers list to quickly create several similar resolvers that target different types and fields.
Synthetic GraphQL APIs must have an API policy to validate the GraphQL request against the schema. In addition, you may want to add authorization rules, rate limiting, and policies for other API level concerns. To update the API policy, select the API Policies tab, then select the </> symbol to reach the XML editor. Here is the minimal policy:
<policies>
<inbound>
<base/>
<validate-graphql-request />
</inbound>
<backend><base /></backend>
<outbound><base /></outbound>
<on-error><base /></on-error>
</policies>
The only required addition is the <validate-graphql-request/> policy. This policy also handles field-level authorization rules for GraphQL. You can add either a <validate-azure-ad-token /> or <validate-jwt /> policy to decode an Authorization header, then use that information to implement authorization rules. Check out the examples in the policy documentation for more information.
Our GitHub sample repository has quite a few example APIs for you to deploy via the Azure Developer CLI, including a Synthetic GraphQL API. This is a terrific way to spin up a set of coordinated samples for learning Azure API Management and Synthetic GraphQL.
Synthetic GraphQL is available now; we hope you'll take it for a spin!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.