AWS Lambda, API Gateway, DynamoDB, Golang でREST APIを作る

#　はじめに
GolangとAWSの勉強がてらに、DynamoDB＋Lambda＋APIGatewayつかってREST APIをつくりました。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/266140/15a4bd62-c30c-bdce-46e4-9bb3dc9519b5.png)

###　参考
> * [golang + Lambda + API GatewayでREST APIを作ってみた](https://qiita.com/icchi_h/items/76f6a0a235e4823d322a)
> * [Amazon API GatewayからAWS Lambdaにパラメータを渡す方法](https://qiita.com/keitakn/items/a409b1722956cb1d9487)

# DynamoDB

今回は簡易的にUserIDとUserNameだけ含むユーザーテーブルを用意します。
テーブルの作り方は”[初めてのサーバーレスアプリケーション開発 ～DynamoDBにテーブルを作成する～](https://dev.classmethod.jp/cloud/aws/serverless-first-dynamodb/)”を参考にしてください

![スクリーンショット 2018-12-11 20.10.14.png](https://qiita-image-store.s3.amazonaws.com/0/266140/ef892693-b071-447f-8657-a2ec4f1f40a3.png)

# Lambda
まずLambdaにDynamoDBへのアクセス権を与えるため、IAMロールを作成しなくてはいけないので
1. **[IAM]** -> **[Roles]** -> **[Create role]** -> **AWS services**から**Lambda**を選択し**[Next Permissions]** -> **[AmazonDynamoDBFullAccess]**と**[AWSLambdaBasicExecutionRole]**を選択し→**[Next Tags]**→**[Next Review]**→**[Create role]**

2. Lambdaのメニューから[**Create function**]を選択して以下のようにLambdaを作成
![スクリーンショット 2018-12-11 20.24.46.png](https://qiita-image-store.s3.amazonaws.com/0/266140/d427b9e1-bdd6-cc07-1941-c442243cf3fe.png)

3. AWSのGoのSDKをインストール

```
$ go get -u -v github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute
$ go get -u -v github.com/aws/aws-lambda-go/lambda
$ go get -u -v github.com/aws/aws-sdk-go/aws
$ go get -u -v github.com/aws/aws-sdk-go/aws/session
$ go get -u -v github.com/aws/aws-sdk-go/service/dynamodb
```
もしくは

```
$ go get -u -v github.com/aws/aws-sdk-go/...
```
ちなみに **-u** のフラグで最新のパッケージがインストールできて、**-v** でインストール経過が確認できます。

## /user/{id}   -  GET
パスパラメータのidと一致するUserIDを持つユーザーデータを返します。
コードはローカルで編集してzipにしてLambdaにアップロードします。

```
$ GOOS=linux go build -o main
$ zip deployment.zip main
```
![スクリーンショット 2018-12-11 20.43.09.png](https://qiita-image-store.s3.amazonaws.com/0/266140/e6af0335-cf77-c3fa-9e70-200d55b99aa9.png)

```go.getuser.go
package main

import (
	"fmt"
	"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"
)

type User struct {
	UserID   string `json:"userid"`
	USerName string `json:"username"`
}

type Request struct {
	ID string `json:"id"`
}

type Response struct {
	Data string `json:"body"`
}

func Handler(request Request) (Response, error) {

	sess, err := session.NewSession()
	if err != nil {
		panic(err)
	}

	svc := dynamodb.New(sess)

	getParams := &dynamodb.GetItemInput{
		TableName: aws.String("User"),
		Key: map[string]*dynamodb.AttributeValue{
			"UserID": {
				S: aws.String(request.ID),
			},
		},
	}

	getItem, getErr := svc.GetItem(getParams)
	if getErr != nil {
		panic(getErr)
	}

	return Response{
		Data: fmt.Sprintln(getItem),
		}, nil
}

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

以下のようにテストすると
![スクリーンショット 2018-12-11 20.48.22.png](https://qiita-image-store.s3.amazonaws.com/0/266140/9cad2258-e7f7-5b93-a09b-a96507c8fed8.png)

帰ってきた！:santa_tone2:
![スクリーンショット 2018-12-11 20.49.06.png](https://qiita-image-store.s3.amazonaws.com/0/266140/534e633e-5426-25a5-b9c8-3a43aa5f997a.png)

## /user/  -POST-

BodyパラメータからIDとUserNameを取得してDynamoDBに書き込む

```go:createuser.go
package main

import (
	"fmt"

	"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"
)

type User struct {
	UserID   string `json:"userid"`
	USerName string `json:"username"`
}

type Response struct {
	Data string `json:"message"`
}

type Request struct {
	ID string `json:"id"`
	UserName string `json:"username"`
}

func Handler(request Request) (Response, error) {
	sess, err := session.NewSession()
	if err != nil {
		panic(err)
	}
	svc := dynamodb.New(sess)
	putParams := &dynamodb.PutItemInput{
		TableName: aws.String("User"),
		Item: map[string]*dynamodb.AttributeValue{
			"UserID": {
				S : aws.String(request.ID),
			},
			"UserName": {
				S : aws.String(request.UserName),
			},
		},
	}
	putItem, putErr := svc.PutItem(putParams)
	if putErr != nil {
		panic(putErr)
	}
	return Response{
		Data: fmt.Sprintln(putItem),
	}, nil
}
func main() {
	lambda.Start(Handler)
}
```

## /user/{id} DELETE

```go:deleteuser.go
package main

import (
	"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"
)

type User struct {
	UserID   string `json:"userid"`
	USerName string `json:"username"`
}

type Request struct {
	ID string `json:"id"`
	UserName string `json:"username"`
}

func Handler(request Request) error {

	sess, err := session.NewSession()
	if err != nil {
		panic(err)
	}

	svc := dynamodb.New(sess)

	deleteParams := &dynamodb.DeleteItemInput{
		TableName: aws.String("User"),
		Key: map[string]*dynamodb.AttributeValue{
			"UserID": {
				S: aws.String(request.ID),
			},
		},
	}
	if _, err := svc.DeleteItem(deleteParams); err != nil{
		panic(err)
	}
	return nil
}

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

**createuser.go**と**deleteuser.go**に関しても同様にzipにしてアップロードしてください:bicyclist:


# API Gateway

1. **[+Create API]** から適当に新しいAPIを作成
![スクリーンショット 2018-12-11 20.59.49.png](https://qiita-image-store.s3.amazonaws.com/0/266140/a3851498-3607-f3e3-aba2-315cec23c56c.png)

## /user/{id}   -  GET
1. [**Actions**] -> [**Create Resource**]から
![スクリーンショット 2018-12-11 21.01.53.png](https://qiita-image-store.s3.amazonaws.com/0/266140/ace36059-124d-66c8-21ee-3bb4b6e48d4a.png)
2. また[**Create Resource**]から
![スクリーンショット 2018-12-11 21.03.48.png](https://qiita-image-store.s3.amazonaws.com/0/266140/1b2f9057-50fc-27b5-3ed1-aa5e66072c21.png)
3. [**Create Method**]から**GET**を選択して、さっき作ったLambdaを選択
![スクリーンショット 2018-12-11 21.05.42.png](https://qiita-image-store.s3.amazonaws.com/0/266140/219930b6-3c98-2847-87a4-2d479e91cc86.png)
4. [**Integration Request**] -> [**Mapping Templates**] を順に選択して、以下のように設定する
![スクリーンショット 2018-12-11 21.09.15.png](https://qiita-image-store.s3.amazonaws.com/0/266140/42e46d8c-aa0d-5618-4d7d-b3609dfd76ef.png)
5. [**Test:zap:**]からパスパラメータにidを指定して実行すると、
![スクリーンショット 2018-12-11 21.10.48.png](https://qiita-image-store.s3.amazonaws.com/0/266140/7b5d8638-45bc-2344-65db-8fdabf5960a2.png)
帰ってきた！:santa_tone1:

## /user/   - POST
Request Bodyにidとusernameを入力して実行:zap:

![スクリーンショット 2018-12-11 21.18.55.png](https://qiita-image-store.s3.amazonaws.com/0/266140/830db5d5-06f1-cc1c-35a2-8c83d48c63e2.png)

# おわり
以上、簡単にLambda＋DynamoDB＋API GatewayでREST APIつくってみました！
DynamoDBからの**GetItemOutput**をjsonで返すやりかた分かる人いたら教えてほしいです。:pray: