Lambda入門#4 API Gatewayとの連携

昨日の続き、やってきます！

# 参考URL
今日も以下の記事を参考にしてやったことを記載しています。

１．APIゲートウェイの設定
https://dev.classmethod.jp/cloud/aws/getting-start-api-gateway/

２．APIゲートウェイのバージョン管理（lambda連携）
https://dev.classmethod.jp/cloud/aws/version-management-with-api-gateway-and-lambda/

## API Gatewayと連携させるlambdaの設定
まずはちゃんとAPIゲートウェイの設定を覚えていきたいと思います。

上記で紹介した１．の記事を参考にまずはAPIゲートウェイのバックエンドになるlambdaを設定しておきます。
AWSが用意しているblueprintを利用します。

lambdaにログインして、[設計図の使用]にチェック入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/9719166e-abb3-b8bc-c96e-22fe6f1821c0.png)

設計図のフィルター欄に「hello」と入力して、「hello-world-python」を選択し、[設定]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/94111b21-844a-a28e-ae90-f08e76626975.png)

関数名は前回までに作成していたものと被らないように気をつけつつ、適当に入力して、[既存のロールを使用する]で前回に作成されたロールを指定しておきます。
※前回同様に「基本的なlambdaアクセス権限で新しいロールを作成」を選択して、新しいロールを自動的に作成しても大丈夫です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/d2d77dc8-7693-f130-e474-1c687222ca54.png)

[関数の作成]を指定し、関数が作成されたらコードを確認してみます。
記事内にコードの内容が説明されていますので、そのまま引用しますね。

>eventがリクエスト元から受け取る内容ですが、「hello-world-python3」では3つの値をprint(CloudWatchに記録される)してkey1をreturnするようになっています。

実際にこのblueprintを使用して作成したlambdaのコードは以下のようになっています。

```python:hello-world-pythonオリジナル
import json

print('Loading function')


def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))
    print("value1 = " + event['key1'])
    print("value2 = " + event['key2'])
    print("value3 = " + event['key3'])
    return event['key1']  # Echo back the first key value
    #raise Exception('Something went wrong')
```

これを記事に従って、以下のように変更してみます。

```python:hello-world-python変更版
import json
 
 
def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    return event
```

受信したイベントの内容をそのまま出力するだけの処理に書き換わっています。
書き換えたら、lambda上でコードの保存を行います。
テストを行うために適当にHello Worldテンプレートを利用したテストイベントを1つ作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/9e2dc78a-5cf9-84f6-27ab-9fd68f736ba0.png)

正常に実行されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/353e4fb1-72f0-48da-6408-054a026a50dc.png)

これでAPI Gatewayと連携させるlambdaの設定は完了です。

## APIゲートウェイの設定
次にAPI Gatewayですが、APIの種類を選択するところからスタートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/558553d7-1e97-dd5b-967d-ebdbcaf6eb25.png)

ここでは[REST API]のエリアに表示されている[構築]をクリックします。
↓のような画面が表示されるので、[新しいAPI]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/8bb8415c-8731-d2a0-8bd2-0f48b01afd61.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/2623d3d1-1f44-aec0-06f8-651fcdfe04d2.png)

API名、説明は任意の内容で設定します。
エンドポイントタイプは[リージョン]とします。
CloudFrontは利用しないし、プライベートのVPCからのアクセスではないためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/5e86fa2c-f001-9979-7984-b2807153546e.png)

ひとまず、出来上がりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/10698929-2650-3130-5a18-c023810627f9.png)

ここから、「リソース」と「メソッド」を作成していきます。
記事に書いてくださっている説明が鬼分かりやすいので、そのまま引用します。

>リソース：簡単に説明するとAPIのパスです。
 メソッド：リソースに対するアクションで、HTTPのメソッド「GET, POST」等と連携します。

## APIゲートウェイ リソースとメソッドの作成

まずはリソースから作成していきます。
[アクション]-[リソースの作成]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/e41c7d9d-f160-98a3-0eca-487831d759d7.png)

オプションはいじらずにリソース名だけ入力して、作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/9f3197fb-6ffa-562f-4f2e-28f7c9f5a353.png)

リソースが出来ました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/579aa39d-f564-ab11-6661-179eac8d3c86.png)

次にこの作成したリソースに対するメソッドを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/768ea773-cdae-93f0-6104-e551de266fdc.png)

プルダウンメニューから選べるので、[POST]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/a558674b-4e94-2b14-65be-8504b9b520ac.png)

✔マークをクリックすると、画面右側にセットアップ画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/633a1f9d-0c8a-256c-29aa-fe78b676e58d.png)

統合タイプに[Lambda関数]を選択し、[Lambda関数]に先ほど作成した関数を指定します。
関数名は途中まで入力すると補完してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/1b657d91-4f3e-0355-02a3-f9923eabe7d2.png)

[保存]をクリックすると、以下のように権限を与える警告が表示されるのですが、ここは[OK]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/2b2af6c9-3806-b262-aefa-1a522fc31837.png)

この完成したメソッドをテストしてみましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/8717645b-7cfe-2b0a-2fb8-ca84222ac7e7.png)

上記、画像の通り、[テスト]という表示がありますので、そちらをクリックします。
[リクエスト本文]に```{"test":1}```と入力して[テスト]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/9c4ce269-4aec-812f-e1ba-37e46708856b.png)

テストは完了し、[レスポンス本文]に先ほど指定した値が返ってくることが確認できました。
ただ、この時点では外部からのアクセスはできないため、外部からもアクセスできるようにデプロイを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/26408353-09fe-5fc9-485b-2e42e1f74db8.png)

デプロイにつきましても、参考にした記事から引用します！

>デプロイ
APIを外部に公開する作業。
初回デプロイ時にはそのAPIのエンドポイント(URL)が生成されます。
デプロイ時にはその段階のリソース・メソッド等の設定を反映したバージョンが作成され、以後デプロイするたびにバージョンが増えます。デプロイされたバージョンの内容を変更することはできません。
エンドポイントに来るリクエストをどのバージョンで処理するかはステージで関連付けます。

そして、もう一つの重要な概念が[ステージ]です。

>ステージ
エンドポイントとデプロイバージョンを紐付けるエイリアスです。
例えば、devとprodという2つのステージを用意しておき、devに最新バージョンのデプロイを行い、prodは安定したバージョンのままにしておき、開発用とエンドユーザに提示するエンドポイントを分けることができます。

要はデプロイで外部に公開できるようになるのですが、本番用の安定バージョンなエンドポイントと開発用の不安定なエンドポイントをエイリアスで分けようっていうことです。

## APIゲートウェイ デプロイ
では、デプロイの設定に入るのですが、外部に公開すると誰でもアクセスできるようになってしまうため、APIキーを作成し、APIリクエスト時に認証が必要になるよう構成します。

画面左側のメニューにある[APIキー]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/74a15707-6aa8-6a70-03b9-847eee2688a4.png)

APIキーの画面に切り替わったら、[アクション]-[APIキーの作成]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/8a0d6857-0613-861f-11e1-2ea0063c1daf.png)

名前は適当につけて、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/401da4c5-3581-aff2-2bd5-36fb3b5150cc.png)

APIキーが出来上がるので、これをメソッドに紐づけます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/f5ef53ea-b419-e3f6-acff-548b73ce4395.png)

また、先ほどまで作成していたPOSTメソッドの画面まで戻り、[メソッドリクエスト]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/7b7852d4-f202-955d-0e13-449a71331e01.png)

この画面で[APIキーの必要性]を[false]から[true]に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/ffb5ef80-c085-0290-ca58-109ae917bef1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/f309f065-a7a2-7bae-60f7-c228d5bbd8f5.png)

trueに変更されたことを画面から確認して、[アクション]の[APIのデプロイ]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/3791511b-f672-6aa9-2381-71c2e0d39d04.png)

ステージは今回に併せて、新規で作成するので、任意の名前で作成し、デプロイします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/b66c537a-2e5a-7e9b-7033-11dd7edc3114.png)

エンドポイントが払い出されました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/6a3f02ea-8d77-94a4-4f04-35b7016b1179.png)

最後に、APIキーとの紐づけを行います。
また、画面左側のメニューから[使用量プラン]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/4ecf90ee-14b4-e51e-0a7a-c5f9881520a6.png)

画面右側のエリアから[作成]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/35bf6401-d092-b7a1-687b-4cbdb667c551.png)

今回は特にスロットリングとクォータの設定は行わずに[次へ]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/7a713796-1a81-a036-b9db-e0d8d9094211.png)

次のAPIステージの追加で先ほど作成したAPIとステージの情報を紐づけます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/803dc189-b246-6f57-29f2-4bcf16be0c45.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/3ba89fcb-0f87-cdfe-9975-a3fbc26da55c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/706edd74-f436-26b2-7b85-4580861e67eb.png)

最後に✔ボタンをクリックして、[次へ]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/98142387-7882-7d3d-e6f0-bd009d04e084.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/6024a15e-1b9f-537f-4685-876047cbd107.png)

ここで、APIキーを使用量プランに追加することでAPIキーがAPIゲートウェイと紐づくようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/2c8658fe-3d2b-caa3-ae2f-c06f339330df.png)

これも途中まで入力すると補完されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/af4bd454-860c-41b7-c4c5-3b546c16a873.png)

✔ボタンをクリックして、[完了]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/e359ed4f-0265-ae5a-3db0-4ae90fcd2113.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138274/5ac631c5-1106-559f-d171-3f946ece4db1.png)

## APIの動作確認
作成したエンドポイントに対して、curlコマンドでアクセスしてみます！

```bash:動作確認コマンド
# APIキーがない場合
$ curl -d '{"test":1}' https://api.example.com/dev/test
{"message":"Forbidden"}
 
# APIキーを指定した場合
$ curl -d '{"test":1}' -H 'x-api-key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' https://api.example.com/dev/test
{"test": 1}
```

上記のURLは適宜、作成したものに変更してみてください。
APIキーがない場合、「Forbidden」のメッセージが返ってくるはずです！

次回もAPIゲートウェイのバージョン管理について続きをやっていきます。