Convert REST APIs to GraphQL with AWS AppSync
Tags: aws, appsync, rest, graphql
Published: 2023-04-06 15:51:39

**REST APIs**

We all have been using REST APIs for a long time now. REST = REpresentation STate. Requests from client are replied with a representation of the state of the resource using HTTP, in one of the uniform formats like JSON. Client and server sends messages back and forth with the representations for changing the state. 

**Disadvantages of REST API**

REST API may give you more data you need. 
Each REST API may be a different endpoint and/or managed separately 
Multiple calls are required to get required data. 

You can see examples for these here: [Github Guide to migrate from REST to GraphQL](https://docs.github.com/en/graphql/guides/migrating-from-rest-to-graphql)

**GraphQL**

Created in 2012 and made public in 2015 by Facebook, GraphQL addresses many of the drawbacks of REST API. 

- You can get just the data you need and nothing more. 
- Single Endpoint structure - no need to manage multiple APIs. 
- Built-in caching, batching, pagination. 

Your own REST APIs you may be able to re-write in GraphQL paradigm, but what if you were using an API that was not controlled by you? AWS Appsync provides you a way to convert a REST API to GraphQL API. 

**AWS AppSync**

AWS AppSync is a managed GraphQL service that makes it easy to connect disparate data sources into a single cohesive API. You define schema that tells what type of data is available and how to query them. Data Sources are the backend services that the API will use to fulfill requests. Resolvers connect data sources with queries and types in schema (and mutations)

**Our REST API**

Our REST API is hosted on AWS API Gateway. It will give you the picture of a random cat image url from the internet. Didn't we invent internet to send each other cat pics?


![REST API on AWS API Gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tk6d7jxveuzq03puaqfw.png)

**AppSync API**

We will get into Appsync and create an API. Select "Build from scratch". Make sure to click the button on the top, the below button is for a different selection.


![API From Scratch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tqyv637wguxgpc44mkx.png)

Now inside this API, select Data Sources and create Data Source. Select HTTP Endpoint and give the hostname of the API Endpoint. 

![HTTP Endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/up1nh326mbg7i60g3ox8.png)


Now our Cat API gives a response like below:

```
   {
        url: "https://i.imgur.com/7X8uJZX.jpg"
    }
```

Inside the API in Appsync, goto Schema and create a schema to describe and query the data from the API. 

```
type Query {
	getURLJSON: AWSJSON
	getURL: String
}

type imgurl {
	url: String
}
```


type Query shows a GET in REST speak. and type imgurl defines a object type called imgurl which can be compared to a model with attributes. Here we have only one field within the object type. We have not included Mutation here, which is graphql method for modifying server-side data. (POST etc.)

**Resolver**

In the schema screen itself, on the resolver side, click on the attach button near the getURL query. 


![Resolver](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eosz9vfwibsutfdeyh6l.png)

Resolver provides a way to map the details in your HTTP request so that it can be mapped to what is needed on the REST API. AWS defaults resolvers to use javascript based pipeline resolvers. This allows you to have a pipeline of functions that will process your request data or response data as it flows through the pipeline. This provides more power at the cost of complexity. We will be doing this the easy way today to illustrate our use case. 

Click on Actions -> Update Runtime -> Change Resolver Type - Unit Resolver -> Select Runtime (VTL) 

Unit Resolver will have one _before mapping template_ and _after mapping template_. VTL stands for Velocity Template Language, a language by Apache for writing templates. _Before mapping template_ will process your request date before it sends to the REST API endpoint. _After mapping template_ will process the data coming from REST API, when it comes from the resolver. VTL also provides facility to add a function if needed. 

Below is a diagram that compares Unit Resolvers and Pipeline Resolvers. (Left side shows the Unit Resolver) 

![Resolvers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ra01asmwp4orbxtvcgy.png)

This image is (c) AWS and from this [documentation](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html)

Our before template:

```
{
    "version": "2018-05-29",
    "method": "GET",
    "resourcePath": "/default/random-cat-api"
}
```

It specifies the HTTP verb to be used (GET) and the resource path which will be appended to the url we gave in the data source definition. 

Our after template:

```
$util.toJson($ctx.result.body) 
```

This just takes the REST API output and converts to JSON. This is required since our REST API was built in dinosaur times and returns a String. If your REST API returns JSON like the good ones, you just use $ctx.result.body

Our resolver will look like: 
![Resolver](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wg36084420t5qzukt8jz.png)

Now how to query this GraphQL API? AppSync provides a Query section for testing out queries. Goto the query section inside the API. Here you define a named query (TestQuery in the below screenshot) and you specify the query name given in the schema (getURL)


![Query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p88w9fylg4296czdt2qj.png)


How will we call the GraphQL API from outside AWS?
You can get the API Endpoint and API Key from the Settings screen in the API. 


![API Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0heme8529njxlommqdi.png)

With this data, lets call this API the old-fashioned way, with cURL. Replace APPSYNCAPIENDPOINT and APPSYNCAPIKEY in below command with actual values. 
```
curl --location --globoff 'https://APPSYNCAPIENDPOINT?query=query%20TestQuery{%20getURL%20}' \
--header 'x-api-key: APPSYNCAPIKEY' \
--header 'Content-Type: application/json'
```

In header we are passing the API Key and the GraphQL query is passed as a parameter query = query TestQuery{ getURL }. In above command, this part is url-encoded which converts spaces to %20.


![Curl Command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/edu5zo42hv3uh0auhkdg.png)


A logical next step to this would be to use this API in AWS Amplify as the API backend for your fullstack app developed using Amplify. We will cover this in the next article.

Hope this was helpful!