AWS Appsync GraphQL with Go
There is plenty of documentation to develop amplify app (reactJS/ NodeJS) based on appsync graphQL API. However, if we have to develop it in GO without configuring the schema from Front End then aws does not provide any getting started tutorial (I was not able to find it) So here I made one :)
Let's develop the AWS appsync GraphQL API in Go (GoLang) application. We will achieve the following in this blog.
- Set up the serverless GO project
- Set up the DynamoDB & define the app data model
- Set up Mapping template & resolver
- Expose the graphQL resolver lambda
- Deploy the application to the AWS
We will be using the serverless framework in this tutorial. Create a AWS account if you don’t have one already. Create the AWS access key (You will also get a secret along with the key). The secret is only shown once, so save it securely somewhere on your computer.
Install the Serverless framework using npm and configure it to use your aws account. (use the key and secret you created earlier)
Npm install -g serverless
serverless config credentials — provider aws — key <access key ID> — secret <secret access key>
Following serverless plugins are required for appsync (more details on their github page)
npm install serverless-appsync-plugin — save-dev
Create the project using aws-go template.
serverless create — template aws-go — path myAppSyncApp
By default the aws-go template project contains hello and world module. Lets rename the hello module to more relevant name. The Serverless create command does not create the mod file so lets create them.
go mod init myAppSyncApp-API
go mod tidy
If you add any more packages- you can fetch the dependencies using the below command.
go get -u <get required dependencies>
Now our project is ready. Let's configure DynamoDB and AppSync
DynamoDB configuration is added to the resources block. We are using the following configuration. Just PK / SK is defined and no GSI is used. PK will be the cognitoID of the user and SK will be the UUID (unique for each todo). Let's also create the storage folder and define the store, record, and todo structs. You can find details about that in the GIT project. Please note we are prefixing pk with “user_” just for convenience.
Create AppSync folder in serverless/appsync. Create the schema file for the graphql. Here is the simple to-do schema that we are going to use.
Once the schema is in place, we need to generate the data model files so we can refer this data in our Go project. We can manually do that or use the gqlgen. Run below command in the appsync folder and it will generate the data model file for us.
go get github.com/99designs/gqlgen
go run github.com/99designs/gqlgen generate
Now every time we make a change to our graphql schema we must run the above commands to reflect the schema changes into our data models. This is the most convenient way to keep the models and schema file in sync.
Setup the mapping template & Resolver
We have defined the query and mutation in our schema. We need to define the resolver mapping template for the query and mutations. In our serverless file this is the setup
Resolvers are the connectors between GraphQl and a data source. They tell AWS AppSync how to translate an incoming GraphQL request into instructions for your backend data source, and how to translate the response from that data source back into a GraphQL response. They are written in Apache Velocity Template Language (VTL), which takes your request as input and outputs a JSON document containing the instructions for the resolver.
In the mapping template lets create the following request template.
Gettodo/request.vtl
Updatetodo/request.vtl
GetTodo & UpdateTodo are going to use the dynamoDB resolver. So as the request templates says, we are going to perform the GetItem operation where the pk and sk match the provided input.
DynamoDB resolver is much simpler to configure, it almost requires no coding. Now let's set up our final lambda resolver. (We could also set this up as the dynamodb resolver but this is done to explain how to use lambda resolver)
When we configure the lambda resolver for any mutation (this was done above in the serverless file) the requested data is passed on to our lambda, where the data is processed, database operations are done and required data is returned.
Set up the lambda resolver
In the appsync/lambda-resolver folder we will create the main.go file where the lambda will be defined. The Event structure is defined as follows.
All the event data is coming from the request.vtl file. Check the payload section of the template. This is how we can pass the data to the lambda and then process it as per our needs. The requests to the lambda will be processed in the router.go on the following line.
func (g GraphQLRouter) Route(ctx context.Context, req Event)
When request data reaches the Route we are checking the field and based on that perform the required action. In this case, we are performing a create operation on the DB when the field is “CreateTodo”
Deploy the app
Deploying the app is the easy part, just run the ./build.sh and serverless deploy command and the app will be deployed to the AWS cloud.
A working code is provided in the public repository at the github. Hope this article will be useful.