golang + Lambda + API GatewayでREST APIを作ってみた

# はじめに
最近、AWS Lambdaがgolangに[対応](https://aws.amazon.com/jp/about-aws/whats-new/2018/01/aws-lambda-supports-go/)しました。

golangの魅力の1つは実行速度。やはりAPIに利用したいという方は多いのではないでしょうか？ これまでもapexを利用することで、[Lambda(apex) + API Gateway構成のgolangを使ったREST API](https://mmyoji.github.io/posts/2017-06-29-golang-lambda-api-gateway/)は開発できました。

今回、lambdaがgolangを公式にサポートしたということで、apexを使わずに作ってみました。試しにGETパラメータをオウム返しする仕様です。

# 1. golang

## 環境の準備
まだ、goの開発環境が無い方はこのあたりを参照。
<http://golang-jp.org/doc/install>

必要なライブラリをインストール

```bash
$ go get github.com/aws/aws-lambda-go/lambda
```

## lambdaで動かすコードを用意
以下のコードを適当な場所に保存。

```go:api-test.go
package main

import (
	"context"
	"github.com/aws/aws-lambda-go/lambda"
)

func HandleRequest(ctx context.Context, params interface{}) (interface{}, error) {
	// TODO your processing
	return params, nil
}

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

lambdaにアップロードするzipファイルを用意。

```bash
$ GOOS=linux GOARCH=amd64 go build -o apitest api-test.go
$ zip apitest.zip apitest
```

# 2. AWS Lambda
1章で作ったgoバイナリをlambdaにアップロードする。

## lambda関数の作成
AWS Lambdaのコンソール→**関数の作成**。
ランタイムに`Go 1.x`を選択。名前はやロールはお好みで
<img width="1310" alt="SS 2018-01-21 21.44.17.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/52859841-9cec-01f4-5d73-809a3fa4c740.jpeg">

左の項目から`API Gateway`を選択。画面下に設定項目が表示される。
<img width="1285" alt="SS 2018-01-21 21.47.35.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/3b9dc7dd-7576-2958-bff4-55bec1c8c931.jpeg">

API名は、次の章で作るAPI Gatewayの名前を選択。ステージやセキュリティはお好みで。
<img width="1292" alt="SS 2018-01-21 21.48.54.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/1603a72f-90e9-a3b6-4364-8fddaab5bbad.jpeg">

前の章で作った、`apitest.zip`をアップロード。ハンドラを先程のハンドラ名`apitest`と統一(でないと実行時にエラー)
※ 画面右上にある保存を押さないとアップロードファイルが反映されないので注意
<img width="1280" alt="SS 2018-01-21 21.52.40.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/ac60ae17-2465-a5bc-2200-cf19eab31218.jpeg">

## テスト
次に、今作っているlambda関数をテストする。
まだ、テストイベントが作成されていないので作る。
画面右上の「テスト」ボタン左側の欄→**テストイベントの編集**
何でもいいんですが、今回はHello Worldを選択。
<img width="819" alt="SS 2018-01-21 21.54.25.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/24d1ea57-d713-d475-b059-1f786f82ab51.jpeg">

先程作ったテストイベントを選択→「テスト」
<img width="754" alt="SS 2018-01-21 21.54.42.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/0fd2e97c-a8f2-55f3-b647-b2cba9cf7cf6.jpeg">

テストイベントの値がそのまま返ってくることが確認できる。
<img width="1261" alt="SS 2018-01-21 21.57.49.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/ed619055-d828-5028-ac2d-ce1a6e65d7f0.jpeg">

# 3. API Gateway
2章で作ったlambda関数とAPI Gatewayを繋げる。

## リソース・メソッドの作成
API Gatewayコンソール→**APIの作成**
適当なAPI名を選択。
<img width="1140" alt="SS 2018-01-21 22.14.58.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/12f54b3f-f7d7-6f2b-9d7d-52978a8dde88.jpeg">

リソースの作成。このリソースがAPIのパスと対応する。
<img width="1139" alt="SS 2018-01-21 22.16.07.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/f590baa4-8724-7765-ff78-bd8a0e93c9d8.jpeg">

<img width="1181" alt="SS 2018-01-21 22.23.47.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/e0a7ed97-7bbd-d963-94e5-613dc768cfbe.jpeg">

メソッドの作成。今回はGETを選択。
<img width="600" alt="SS 2018-01-21 22.17.51.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/6d219dc7-3679-9548-d886-eb2740d1c138.jpeg">

<img width="374" alt="SS 2018-01-21 22.24.10.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/b6c81c5d-483d-3a15-226c-b7b47fcaa811.jpeg">

2章で選択したlambda関数を選択。途中まで入力すると自動で候補が表示されるはず。
<img width="1190" alt="SS 2018-01-21 22.24.51.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/50b6a4d4-6a7e-21a0-3316-6f3020e82d59.jpeg">

## リクエストの編集
メソッドが作成されると「メソッドの実行」画面に遷移する。
<img width="1178" alt="SS 2018-01-21 22.28.34.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/26cfa104-1774-3de4-5bb7-b19721553eb8.jpeg">

メソッドリクエストに移動し、下図の様にGETパラメータを設定。今回は`hoge`パラメータを用意。
<img width="1400" alt="SS 2018-01-21 22.29.43.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/763e27b0-eccf-be4a-7bfa-560ec4232312.jpeg">

「メソッドの実行」画面に戻り、統合リクエストを選択。
<img width="1397" alt="SS 2018-01-21 22.31.50.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/9e555398-a843-63bc-e79a-9df163530381.jpeg">

本文マッピングのテンプレートのContent-Typeは`Application/json`。
<img width="1182" alt="SS 2018-01-21 22.32.27.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/8b42bf6e-9a09-34c6-1c1f-ed359c56d6f1.jpeg">

テンプレートの内容はこんな感じ。

```
#set($inputRoot = $input.path('$'))
{
    "hoge" : "$input.params('hoge')"
}
```

## テスト
APIの機能面はこれで出来上がったので、ちゃんと動作するかテスト。
「メソッドの実行」画面の左上にある**テスト**を選択。

`hoge`パラメータの中身を入力してテスト。
するとGETパラメータがそのままAPIのレスポンスとして返ってきている。
<img width="1173" alt="SS 2018-01-21 22.33.17.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/20e8b3c8-3815-abc7-de60-e651f53dda2c.jpeg">

## デプロイ
作成したAPIの画面に戻り、アクション→APIのデプロイ
<img width="920" alt="SS 2018-01-21 22.53.24.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/b4a172d4-a8d3-d132-1ccf-0707e8461847.jpeg">

# 終わりに
goでREST APIを作るんだったらEC2上でwebサーバーをたてても良いんですが、やっぱりサーバーレス構成だと保守が楽ですね。