Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ serverless install -u https://github.com/serverless/examples/tree/master/folder-
| [Aws Golang Auth Examples](https://github.com/serverless/examples/tree/master/aws-golang-auth-examples) <br/> These example shows how to run a Golang lambda with authentication | golang |
| [Aws Golang Dynamo Stream To Elasticsearch](https://github.com/serverless/examples/tree/master/aws-golang-dynamo-stream-to-elasticsearch) <br/> This example deploys a DynamoDB Table, an Elasticsearch Node, and a lambda triggered off of a Dynamo Stream which updates an elasticsearch index with the data from the Dynamo Table | golang |
| [Aws Golang Http Get Post](https://github.com/serverless/examples/tree/master/aws-golang-http-get-post) <br/> Example on Making Parameterized Get and Post Request with Golang | golang |
| [Aws Golang Rest Api With Dynamodb](https://github.com/serverless/examples/tree/master/aws-golang-rest-api-with-dynamodb) <br/> Serverless CRUD service exposing a REST HTTP interface | golang |
| [Aws Golang Simple Http Endpoint](https://github.com/serverless/examples/tree/master/aws-golang-simple-http-endpoint) <br/> Example demonstrates how to setup a simple HTTP GET endpoint with golang | golang |
| [Aws Golang Stream Kinesis To Elasticsearch](https://github.com/serverless/examples/tree/master/aws-golang-stream-kinesis-to-elasticsearch) <br/> Pull data from AWS Kinesis streams and forward to elasticsearch | golang |
| [Aws Alexa Skill](https://github.com/serverless/examples/tree/master/aws-node-alexa-skill) <br/> This example demonstrates how to use an AWS Lambdas for your custom Alexa skill. | nodeJS |
Expand Down
20 changes: 20 additions & 0 deletions aws-golang-rest-api-with-dynamodb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.serverless
bin
*.pyc
*.pyo

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
21 changes: 21 additions & 0 deletions aws-golang-rest-api-with-dynamodb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.PHONY: build clean deploy

build:
env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/create todos/create.go
env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/delete todos/delete.go
env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/get todos/get.go
env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/list todos/list.go
env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/update todos/update.go

clean:
rm -rf ./bin ./vendor Gopkg.lock

deploy: clean build
sls deploy --verbose

format:
gofmt -w todos/create.go
gofmt -w todos/delete.go
gofmt -w todos/get.go
gofmt -w todos/list.go
gofmt -w todos/update.go
72 changes: 72 additions & 0 deletions aws-golang-rest-api-with-dynamodb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!--
title: 'aws-golang-rest-api-with-dynamodb'
description: 'Boilerplate code for Golang CRUD Operations'
framework: v1
platform: AWS
language: Go
authorLink: 'https://github.com/gsweene2'
authorName: 'Garrett Sweeney'
authorAvatar: 'https://avatars.githubusercontent.com/u/14845943?s=400&u=6d79e8f042cd3d30643ba4598515cae24be69ec3&v=4'
-->
# aws-golang-rest-api-with-dynamodb

Build & Deploy
```
make deploy
```

# CRUD Operations

## Create

```
curl --request POST \
--url https://fz3n8nstdf.execute-api.us-east-1.amazonaws.com/dev/todos \
--header 'Content-Type: application/json' \
--data '{
"Title": "Walk the Dog",
"Details": "Complete before 11am"
}'

curl --request POST \
--url https://fz3n8nstdf.execute-api.us-east-1.amazonaws.com/dev/todos \
--header 'Content-Type: application/json' \
--data '{
"Title": "Mow the Lawn",
"Details": "Remember to buy gas"
}'
```

## Read

```
curl --request GET \
--url https://fz3n8nstdf.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
```

## Update

```
curl --request PUT \
--url https://fz3n8nstdf.execute-api.us-east-1.amazonaws.com/dev/todos/0d2263b7-c62d-4df6-8503-bb16ee8dd81 \
--header 'Content-Type: application/json' \
--data '{
"title": "Updated title",
"details": "Updated details"
}'
```

## List

```
curl --request GET \
--url https://fz3n8nstdf.execute-api.us-east-1.amazonaws.com/dev/todos
```


## Delete

```
curl --request DELETE \
--url https://fz3n8nstdf.execute-api.us-east-1.amazonaws.com/dev/todos/0d2263b7-c62d-4df6-8503-bb16ee8dd81
```
9 changes: 9 additions & 0 deletions aws-golang-rest-api-with-dynamodb/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/serverless/examples/aws-golang-rest-api-with-dynamodb

go 1.15

require (
github.com/aws/aws-lambda-go v1.22.0
github.com/aws/aws-sdk-go v1.37.1 // indirect
github.com/google/uuid v1.2.0 // indirect
)
36 changes: 36 additions & 0 deletions aws-golang-rest-api-with-dynamodb/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-lambda-go v1.22.0 h1:X7BKqIdfoJcbsEIi+Lrt5YjX1HnZexIbNWOQgkYKgfE=
github.com/aws/aws-lambda-go v1.22.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU=
github.com/aws/aws-sdk-go v1.37.1 h1:BTHmuN+gzhxkvU9sac2tZvaY0gV9ihbHw+KxZOecYvY=
github.com/aws/aws-sdk-go v1.37.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
7 changes: 7 additions & 0 deletions aws-golang-rest-api-with-dynamodb/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "aws-golang-rest-api-with-dynamodb",
"version": "1.0.0",
"description": "Serverless CRUD service exposing a REST HTTP interface",
"author": "",
"license": "MIT"
}
95 changes: 95 additions & 0 deletions aws-golang-rest-api-with-dynamodb/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
app: aws-golang-rest-api-with-dynamodb
service: aws-golang-rest-api-with-dynamodb

frameworkVersion: ">=1.1.0 <=2.1.1"

provider:
name: aws
runtime: go1.x
environment:
DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"

functions:
create:
handler: bin/create
package:
include:
- ./bin/create
events:
- http:
path: todos
method: post
cors: true

list:
handler: bin/list
package:
include:
- ./bin/list
events:
- http:
path: todos
method: get
cors: true

get:
handler: bin/get
package:
include:
- ./bin/get
events:
- http:
path: todos/{id}
method: get
cors: true

update:
handler: bin/update
package:
include:
- ./bin/update
events:
- http:
path: todos/{id}
method: put
cors: true

delete:
handler: bin/delete
package:
include:
- ./bin/deleteBin
events:
- http:
path: todos/{id}
method: delete
cors: true

resources:
Resources:
TodosDynamoDbTable:
Type: 'AWS::DynamoDB::Table'
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
-
AttributeName: id
AttributeType: S
KeySchema:
-
AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
90 changes: 90 additions & 0 deletions aws-golang-rest-api-with-dynamodb/todos/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/google/uuid"

"encoding/json"
"fmt"
"os"
)

type Item struct {
Id string `json:"id,omitempty"`
Title string `json:"title"`
Details string `json:"details"`
}

func Handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

// Creating session for client
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))

// Create DynamoDB client
svc := dynamodb.New(sess)

// New uuid for item id
itemUuid := uuid.New().String()

fmt.Println("Generated new item uuid:", itemUuid)

// Unmarshal to Item to access object properties
itemString := request.Body
itemStruct := Item{}
json.Unmarshal([]byte(itemString), &itemStruct)

if itemStruct.Title == "" {
return events.APIGatewayProxyResponse{StatusCode: 400}, nil
}

// Create new item of type item
item := Item{
Id: itemUuid,
Title: itemStruct.Title,
Details: itemStruct.Details,
}

// Marshal to dynamobb item
av, err := dynamodbattribute.MarshalMap(item)
if err != nil {
fmt.Println("Error marshalling item: ", err.Error())
return events.APIGatewayProxyResponse{StatusCode: 500}, nil
}

tableName := os.Getenv("DYNAMODB_TABLE")

// Build put item input
fmt.Println("Putting item: %v", av)
input := &dynamodb.PutItemInput{
Item: av,
TableName: aws.String(tableName),
}

// PutItem request
_, err = svc.PutItem(input)

// Checking for errors, return error
if err != nil {
fmt.Println("Got error calling PutItem: ", err.Error())
return events.APIGatewayProxyResponse{StatusCode: 500}, nil
}

// Marshal item to return
itemMarshalled, err := json.Marshal(item)

fmt.Println("Returning item: ", string(itemMarshalled))

//Returning response with AWS Lambda Proxy Response
return events.APIGatewayProxyResponse{Body: string(itemMarshalled), StatusCode: 200}, nil
}

func main() {
lambda.Start(Handler)
}
Loading