AWS API Gatewayを使ってDynamoDBにデータを読み書きしてみた

# API Gatewayとは
API Gatewayは乱暴な言い方をするとAPIを提供するための仕組みで、APIのバージョン管理、認証機能の追加を容易にしている。API GatewayはAWS Lamdaや他のWeb API呼び出しと接続することができる。例えば、認証機能を持たないWeb APIに対して、API Gatewayで認証機能を追加することが簡単にできる。今回はAPI GatewayとLamdaを接続し、DyanamoDBに読み書きをする簡単な例を記述します。

# リージョンについて
2015.09.01現在はUS-EAST, US-WEST, EU(アイルランド)の3リージョンのみ対応しているので注意が必要。Tokyoリージョンでは現状使えません。LamdaのメニューからはAPI Gateway + Lamdaで作成できるBlueprintがTokyoでも有効なので注意が必要です。私自身、Tokyoリージョンでこれを使って、得体の知れないエラーが出て迷いました。

# DynamoDBにテーブルの用意
Dynamo DBに以下のmember表の追加(POST)と閲覧(GET)をします。
単純にユーザ名とグループ名です。
```
Table Name : members
Primary Key : user_name (ユーザ名)
Column : group (グループ名)
```
テーブルの作成は以下のように行っていきます。

![スクリーンショット 2015-09-01 19.32.50.png](https://qiita-image-store.s3.amazonaws.com/0/85182/94f8e467-aa77-6a81-3462-173c289952fc.png)

![スクリーンショット 2015-09-01 19.34.52.png](https://qiita-image-store.s3.amazonaws.com/0/85182/4c6b01ae-61e2-6ca9-4e6c-370734731262.png)

![スクリーンショット 2015-09-01 19.36.03.png](https://qiita-image-store.s3.amazonaws.com/0/85182/53458992-ffe3-0fa8-35c1-86aa676c01af.png)

# Lamdaスクリプトの用意
membersというリソースに対して、追加(POST)と閲覧(GET)を行うシンプルな例を作成します。他にも方法があるかと思うのですが、今回は、それぞれの操作に対してLamdaスクリプトを一つづつ用意するという方法を取ります。

以下はユーザの追加のスクリプトです。LamdaスクリプトはシンプルにJavaScriptを選択します。

![スクリーンショット 2015-09-01 19.46.32.png](https://qiita-image-store.s3.amazonaws.com/0/85182/42044a37-76e9-85bc-ade4-8f4f0150289f.png)

POSTリクエストのボディデータは、eventに入ります。event.user_name, event.groupは取り出し、DynamoDBの書き込みをするリクエストを作成します。

次に、閲覧のためのLamdaスクリプトも作成します。"members"テーブルに対してscanするだけなのでとてもシンプルです。

![スクリーンショット 2015-09-08 19.17.35.png](https://qiita-image-store.s3.amazonaws.com/0/85182/ca7ac8df-bf31-e097-f1cb-0998ae2c7e33.png)


```js
console.log('Loading function');

var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();

exports.handler = function(event, context) {
    //console.log('Received event:', JSON.stringify(event, null, 2));

    var params = {
        "TableName": "members"
    }
    dynamo.scan(params, function(err, data) {
        if (err) {
            context.fail(new Error('Unknown error occured'))
        } else {
            var response = {"members":data.Items}
            context.succeed(response)
        }
    })
};
```

これで、API Gatewayを使う準備ができました。

# API Gatewayの設定とデプロイ
API Gatewayサービスを選択して、リソース"members"を追加します。

![スクリーンショット 2015-09-01 19.57.03.png](https://qiita-image-store.s3.amazonaws.com/0/85182/03638f11-cccc-17c0-f7dd-85d0fb340b46.png)

![スクリーンショット 2015-09-01 19.57.41.png](https://qiita-image-store.s3.amazonaws.com/0/85182/9a26ffcb-2499-9130-6027-7e53be7ba181.png)

次に"members"リソースに対して、POST/GETメソッドを追加し、先ほど作成したLamdaスクリプトを割り当てます。

![スクリーンショット 2015-09-01 19.59.35.png](https://qiita-image-store.s3.amazonaws.com/0/85182/009b71e0-6165-5edd-bc06-80f7d499323f.png)

![スクリーンショット 2015-09-01 20.00.28.png](https://qiita-image-store.s3.amazonaws.com/0/85182/b4b6cbde-89ed-6702-135e-4e40ccad0c95.png)

あとは"Deploy API"を押すとURIが割り当てられアクセス可能となります。

# テスト
最初はデータがないと思いますので、PostmanなどでPOSTをしてみて下さい。
https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en

以下POSTする例です

![スクリーンショット 2015-09-03 23.37.48.png](https://qiita-image-store.s3.amazonaws.com/0/85182/eada6a67-0a6e-ce20-6b87-95692962a97a.png)

DynamoDBにちゃんと足されています
![スクリーンショット 2015-09-03 23.39.20.png](https://qiita-image-store.s3.amazonaws.com/0/85182/0f072399-dae3-91a4-0b2a-79a092dd4564.png)

次にBrowserなどでGETを呼び出すとちゃんと登録した値が返却されることが確認できます

```json
{
    Count: 1,
    Items: [
        {
            group: "hyogo",
            user_name: "nakamura"
        }
    ],
    ScannedCount: 1
}
```

# API Keyの追加
このままでは、誰でもPOSTできてしまうので、API Keyをセットします。API Gatewayの最大の利点は、認証の追加削除がコンソールで簡単にできるところだと個人的には思います。

まずAPI Keyの追加を行います。API Gatewayのメニュー"APIs"のAPI Keysを選択して下さい

![スクリーンショット 2015-09-04 11.36.51.png](https://qiita-image-store.s3.amazonaws.com/0/85182/83e01ea4-547b-7994-9db8-87829964e441.png)

API Keyを作成し、ステージングされているAPIとの関連を付けて下さい "API Stage Association"の部分です

![スクリーンショット 2015-09-04 11.38.33.png](https://qiita-image-store.s3.amazonaws.com/0/85182/5bb41b96-6027-2b8b-4d4f-93b6d42671fd.png)

次にリソース"members"のPOSTメソッドのMethod Requestを選択して下さい

![スクリーンショット 2015-09-04 11.39.22.png](https://qiita-image-store.s3.amazonaws.com/0/85182/4d198f40-83f2-17c8-e8ce-8da1fce6b5d9.png)

API Key RequiredをTrueに変更。その後、Deployして下さい

![スクリーンショット 2015-09-04 11.41.11.png](https://qiita-image-store.s3.amazonaws.com/0/85182/8fb6f027-a075-6570-f180-b992ae3d2067.png)

次にPostmanでテストしてみましょう。先ほどと同様にAPI Keyを付加せずPOSTしてみます

![スクリーンショット 2015-09-04 11.44.43.png](https://qiita-image-store.s3.amazonaws.com/0/85182/ae8dc006-d736-ee37-df2f-413e7c5e1843.png)

ただしく失敗します。

![スクリーンショット 2015-09-04 11.44.58.png](https://qiita-image-store.s3.amazonaws.com/0/85182/3314923c-bec7-688e-f9c8-b01376913b0c.png)

次にヘッダで"x-api-key"で先ほど作成したAPI Keyを付加します

![スクリーンショット 2015-09-04 11.48.58.png](https://qiita-image-store.s3.amazonaws.com/0/85182/4a9539ce-e7a6-3ae9-19a2-b6e925708ec8.png)

その場合はちゃんと成功することが確認できました

![スクリーンショット 2015-09-04 11.50.05.png](https://qiita-image-store.s3.amazonaws.com/0/85182/a7a9383d-3b7f-804f-bd60-fccde6d2c6bf.png)

またブラウザなどでGETメソッドの呼び出しをした場合は、API Keyがなくても読めることが確認できます

```json
{
    Count: 2,
    Items: [
        {
            group: "hyogo",
            user_name: "nakamura"
        },
        {
            group: "nara",
            user_name: "imiya"
        }
    ],
    ScannedCount: 2
}
```