[AWS.3] Lambda関数へのトリガー追加 (API Gateway)

# 1. 概要
AWS.1 および AWS.2 は、すでに広まっている情報を思いっ切り焼き直した記事でした。
もう少し高度なサンプルも予定していますが、その前に作成済みの Lambda 関数を Amazon API Gateway に対応させてインターネットから簡便に呼び出せるようにしておきます。

## Amazon API Gateway とは
バックエンドで動くビジネスロジックへアクセスするための「フロントドア」として機能する仕組み、とのことです。
具体的には RESTful API や WebSocket API の作成・公開・管理 を一手に担い、Lambda 関数をはじめとするビジネスロジックへアクセする「API」を提供します。

Amazon API Gateway
https://aws.amazon.com/jp/api-gateway/

### Lambda プロキシ統合について
API Gateway を利用する際は、クライアントから渡される情報を「呼び出し先のロジックがアクセスできる領域」へマッピングする必要がありました。
マッピングの考え方自体はともかく、定義を記述するための書式が多少難解でメンテナンス性も悪かった模様です。

「Lambdaプロキシ統合」はこのマッピング作業を不要とし、呼び出し元から渡されるパラメータをそのまま Lambda　関数へ引き渡してくれる機能です。

様々な制約もあるようですが、余計な作業が無くなることは開発者にとっては嬉しい限りです。
API Gateway の既定の設定では 「**Lambdaプロキシ統合 を使用する**」となっているので、特に必要なければ積極的に利用すべきでしょう。

API Gateway で Lambda プロキシ統合を設定する
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html

### Lambda 関数の改造（API Gateway 対応）
Lambdaプロキシ統合 を利用するにあたり、作成済みの サンプル関数 を改造する必要があります。
関数の入力形式 および 出力形式を プロキシ統合 で利用可能な形に変更しなければならないためです。

#### (1) Lambda 関数の入力形式
呼び出し元から渡されるパラメータは、Lambda 関数の event パラメータへマッピングされます。
Key&Value コレクションに格納された形で提供されるので、パラメータ名を指定して値を取り出す必要があります。

プロキシ統合のための Lambda 関数の入力形式
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

#### （２） Lambda 関数の出力形式
関数が返却する戻り値は、下記の書式を持つ JSON形式データ でなければなりません。
```JSON
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}
```
この書式に従わない場合、API Gateway は呼び出し元に対して「<font color="red">502 Bad Gateway エラーレスポンス</font>」を返却します。

プロキシ統合のための Lambda 関数の出力形式
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format

# 2. Lambda 関数サンプルの改造
サンプルの Lambda 関数を API Gateway に対応させ、RSETful API で呼び出せるように改造します。
なお、RESTful API では入出力データを標準的なデータフォーマット（XMLやJSON）でやりとりしますが、今回の改造では割愛して単純な文字列を受け渡すのみとします。

### 改造箇所
1. API Getway 用の NuGet パッケージを導入。
1. Lambda 関数の引数と戻り値のデータ型を、API Gateway 用に変更。
1. 呼び出し元から渡された文字列を、eventパラメータから取り出すように変更。
1. 返却する文字列を、戻り値用のデータオブジェクトへ格納するように変更。

### (1) API Getway 用の NuGet パッケージを導入
サンプルプロジェクトで「NuGet パッケージの管理」を開き、「Amazon.Lambda.APIGatewayEvents」を導入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90456/34a85a47-c28c-dae6-7b5e-8f5cba12a9d2.png)

### (2) Lambda 関数の改造

```C#
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using System.Net;

（中略）

public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
{
    string input = "<none>";

    //*******************************
    // 引数の抽出
    //*******************************

    if ((request.QueryStringParameters != null)
        && (request.QueryStringParameters.ContainsKey("Param1") == true))
    {
        // クエリ文字列でオプション指定されている場合は、Param11 の値を取り出す。
        input = request.QueryStringParameters["Param1"];
    }
    else if (String.IsNullOrEmpty(request.Body) == false)
    {
        // リクエスト本文が存在する場合は、その内容を取り出す。
        input = request.Body;
    }

    //*******************************
    // Echo文字列の合成
    //*******************************

    string dt = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff");
    string retEcho = String.Format($"[{dt}] echo: {input}");

    //*******************************
    // 返却値（レスポンスデータ）の構築
    //*******************************

    return new APIGatewayProxyResponse
    {
        StatusCode = (int)HttpStatusCode.OK,
        Body = retEcho
    };
}
```
AWS.2 で作成した関数とは大きく異なります。
まず、戻り値 と 第１引数のデータ型 が string型から変更され、API Gateway 対応のデータ型になりました。
|データ型|説明|
|:---|:----|
|APIGatewayProxyRequest|呼び出し元から渡された入力パラメータを含め、リクエストに関する全ての情報が格納されている。|
|APIGatewayProxyResponse|API Gateway が呼び出し元に返却するレスポンスデータを構成する。|

前回のサンプルでは第１引数で受け取った文字列ですが、改造後は APIGatewayProxyRequest オブジェクトから「クエリ文字列」または「Bodyデータ」として取り出しています。

また、前回は単なる戻り値として返却していた「Echo文字列」も、APIGatewayProxyResponse オブジェクトの「Bodyデータ」として格納するように変更しました。

### (3) パッケージ化 ＆ デプロイ
前回のサンプル作成時と変わりません。
```dotnet lambda deploy-function```コマンドで実施してください。

# 3. RESRful API の作成 (API Gateway)
API Gateway の管理画面から作成することもできますが、Lambda 関数 管理画面の「トリガーを追加」ボタンをクリックして進めた方が、手間をかけず簡単に作成できます。

「関数の概要」画面を表示した後、「+ トリガーを追加」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90456/64a9ff03-b532-363b-981a-6fd790e4183a.png)

「トリガーの設定」画面のドロップダウンリストの中から「API Gateway」を選択します。
その後「Create a new API」および「REST API」を選び、Securityドロップダウンリストからは「Open（認証なし）」を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90456/ac1b548c-7b0c-744a-6f5a-0627ac52426a.png)

[追加]ボタンをクリックするとトリガーが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90456/1a092ace-852c-e694-e55d-bfd06059224b.png)

Lambda 関数の管理画面の下には、追加したトリガーの詳細が表示されています。
太字のAPI名（EchoSample-API）をクリックすると、API Gateway の管理画面へ切り替わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90456/6a9a5b5b-48a3-9667-46d4-e6138668d226.png)

API「EchoSample-API」の詳細画面（API Gateway 管理画面内）が表示されます。
下図の「テスト」というリンクをクリックすると、Lambda 関数の呼び出しテストを行う画面が表示されますが、詳細手順は 次回 説明することにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90456/aa9d4e74-77fa-d3ad-fdc2-c267dba70a35.png)

# 4. 終わりに
本記事で記載したように、Lambda 関数を呼び出す API を作成するのは非常に簡単です。
ほとんどの設定が「既定値」とは言え、このサンプルはすでにインターネットからアクセス可能な状態にあり、ブラウザからアクセスして関数の返却値を表示させることも可能です。

次回は、API Gateway 管理画面から lambda 関数を呼び出す「テスト」を実施してみます。