【AWS】API Gateway + LambdaでAPIをつくる


## やりたいこと
サーバを使わずにAPIを作成したい。
EC2インスタンスからAPI Gatewayで作成したREST APIにリクエストを投げて返ってくるのを確認します。
<img width="600" alt="Qiita logo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/03bb2b75-3fc5-d8d7-9de3-d08acf2a7858.png"> 


## 手順
Amazon API GatewayとLambdaを使用して、REST APIを作成してみます。

[1. Lambda関数を作成する](#1-lambda%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)
[2. API GatewayでREST APIを作成する](#2-api-gateway%E3%81%A7rest-api%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)
[3. REST APIをデプロイする](#3-rest-api%E3%82%92%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B)
[4. 2番目のLambda関数を作成する](#4-2%E7%95%AA%E7%9B%AE%E3%81%AElambda%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)
[5. API GatewayでREST APIにリソース、メソッド、パラメータを追加する](#5-api-gateway%E3%81%A7rest-api%E3%81%AB%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)

参考：https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-getting-started-with-rest-apis.html

## 1. Lambda関数を作成する
API Gatewayを作成する際に、Lambda関数を指定する必要があるので、先にLambda関数を作成します。

Lambdaのコンソール画面から「関数」→「関数の作成」を選択します。
関数の作成画面で「一から作成」を選択します。

関数名： my-function
ランタイム： Python 3.7
を設定して「関数の作成」を押下します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/13ad5c6b-14d5-82c5-cc1e-f9f8533aede4.png)

「関数 my-functionを正常に作成しました。」と出れば関数の作成は完了です。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/65001654-ebe0-f687-24a1-b2e7843fa052.png)

ちなみに、作成した関数はデフォルトで「Hello from Lambda!」を返すようになっています。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/cebd9fd3-f119-8c44-b73e-f0e4dcfb4ca6.png)


## 2. API GatewayでREST APIを作成する
API Gatewayのコンソール画面から「APIの作成」を押下します。
今回は検証なので、「REST API プライベート」で「構築」を選択します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/153f13fb-b581-ed86-2592-e29707d3c0db.png)

ポップアップが出るのでOKを選択します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/9d603477-032a-2b4d-ab22-a29ff7ad1387.png)

下記画像のように設定していきます。
選択と入力が完了したら、「APIの作成」を押下します。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/ca0a9fa0-a577-a3af-cfa8-2a04587d0664.png)

完了すると「/」のみが表示されます。
この「/」がルートレベルのリソースであり、APIのベースパスのURLに対応しています。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/eb7a66a9-7f09-09d9-bdf5-6f901079d4ad.png)

次にメソッドの追加を行います。
「アクション」→「メソッドの作成」を選択します。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/58dc670f-d266-bd8b-eaa2-173e1d01a8a2.png)

「GET」を選択し、チェックマークを押下します。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/e8e2cff8-92a4-4405-8a7e-41d875a572ac.png)

すると、GETのセットアップ画面になるので、必要事項を入力して、「保存」します。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/70131be5-5392-1cde-6d1a-3ab93c166d03.png)

設定された内容が表示されます。
各項目の詳細については<a href=https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-create-api.html>公式</a>をご参照ください。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/b34b4fd2-873a-38b8-7a7e-677f75faf62f.png)

REST APIの作成はここで完了です。

## 3. REST APIをデプロイする
実際に使用するには、作成したREST APIをデプロイする必要があります。

作成したREST APIの「アクション」→「APIのデプロイ」を選択します。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/7b5aa068-9420-370f-2277-220e21ff6394.png)

ポップアップが出現するので、「新しいステージ」を選択し、
ステージ名を「dev」にして「デプロイ」を押下します。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/f4097e9b-cb28-3e88-0acd-c675cb32167c.png)

すると、ステージエディターの画面が表示されURLの呼び出しのURLで実際にAPIにリクエストを送ることができます。
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/db448bf0-4a30-1e9d-cffc-6a3b746937e0.png)

EC2インスタンスから実際にリクエストを投げてみましょう。

```
$ curl -X GET '呼び出しのURL'

"Hello from Lambda!"
```
設定しているLambdaが返却する「Hello from Lambda!」がレスポンスされればOKです。

## 4. 2番目のLambda関数を作成する
次に、GETリクエストでパラメータを持つパターンも行っていきます。
先ほどのAPIではLambdaが固定値で'Hello from Lambda!'を返却するようになっていました。
なので、今回は受け取ったGETリクエストのパラメータをレスポンスに乗せるようなLambdaでAPIを作成していきます。

先ほどと同じ要領でLambda関数を作成していきます。
関数名：my-function2
ランタイム：Python 3.7
実行ロール：既存のロールを使用するで先ほど作成したロールを選択します。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/ac8eab7a-2ac8-f44f-20ca-5ec2354ef5a0.png)

作成が完了したら、関数コードを書き換えます。
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/29543324-a5b6-05cd-2b24-233709781155.png)

受け取ったパラメータをレスポンスに乗せるようにします。

```python:lambda_function.py
import json

def lambda_handler(event, context):
    myParam = event['myParam']
    return {
        'statusCode': 200,
        'body': json.dumps(myParam)
    }
```

Lambdaの設定は完了です。

## 5. API GatewayでREST APIにリソース、メソッド、パラメータを追加する
API Gatewayでリソースの作成をしていきます。

「アクション」→「リソースの作成」
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/dbd00460-31ed-549a-b268-81f1e579aad0.png)

リソース名：my-resource
→「リソースの作成」
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/358f3811-b5c6-41d7-3e48-39204264ab3d.png)

次にメソッドの作成をしていきます。
my-resourceを選択した状態で、「アクション」→「メソッドの作成」
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/b1929a06-4181-96f6-10b9-16a63e504365.png)

「GET」を選択してチェックボタンで決定する。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/09f1ff3e-39c3-a5f3-d554-a50131696464.png)

my-resource GETのセットアップ画面になるので、Lambda関数に先ほど作成した「my-function2」を選択して保存する。
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/be610c83-7469-5cce-4869-78233805c6e6.png)

権限追加のポップアップが出るので、「OK」
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/035b85f6-600b-9118-472f-742f2c652967.png)

メソッドの実行画面で「統合リクエスト」を選択します。
![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/5672292b-3070-3d1f-70ac-b95372ba2d23.png)

下の方に「マッピングテンプレート」の設定があるので、
リクエスト本文のパススルー：テンプレートが定義されていない場合（推奨）
Content-Type：application/json
を指定します。
![25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/ca596b31-b165-127a-65e0-569492bf9625.png)

テンプレートを入力して保存します。
![26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/4ab63ede-ce07-cd56-5025-3f90163510f4.png)

```:テンプレート
{
    "myParam": "$input.params('myParam')"
}
```

これで、リクエストパラメータの"myParam"という項目をLambda関数側でevent['myParam']で取得できるようになります。

```python:lambda_function.py
import json

def lambda_handler(event, context):
    myParam = event['myParam'] #←ここ
    return {
        'statusCode': 200,
        'body': json.dumps(myParam)
    }
```

これでAPI側の設定は完了になりますので、先ほどと同様にデプロイして実行してみます。

## 確認してみる
パラメータに「my-resource?myParam=Hello%20from%20API%20Gateway!」を付与してリクエストしてみます。

```
$ curl -X GET 'https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/my-resource?myParam=Hello%20from%20API%20Gateway!'

{"statusCode": 200, "body": "\"Hello from API Gateway!\""}
```

リクエストパラメータに付与した「Hello from API Gateway!」がbodyとしてレスポンスすることを確認できました。

今回は必要最低限の設定で実施したので、導入する際はもっと調査が必要になりそうですが、サーバレスとしてのAPI Gateway + Lambdaの全体像はつかめたかと思います。