

# チュートリアル: 2 つの AWS サービス統合と 1 つの Lambda 非プロキシ統合を使用して計算ツールの REST API を作成する
<a name="integrating-api-with-aws-services-lambda"></a>

[チュートリアル: Lambda 非プロキシ統合を使用して REST API を作成する](getting-started-lambda-non-proxy-integration.md) は `Lambda Function` 統合のみを使用します。`Lambda Function` 統合は、Lambda 関数を呼び出すために必要なリソースベースのアクセス許可を自動的に追加するなど、統合設定の多くを実行する `AWS Service` 統合タイプの特殊なケースです。ここでは、3 つの統合のうち 2 つが `AWS Service` 統合を使用しています。この統合タイプでは、より細かく制御できますが、適切なアクセス許可を含む IAM ロールの作成や指定などのタスクを手動で実行する必要があります。



このチュートリアルでは、基本的な算術演算を実装し、JSON 形式の入出力を受け入れて返す `Calc` Lambda 関数を作成します。次に、REST API を作成し、それを Lambda 関数と以下の方法で統合します。

1. `GET` リソースで `/calc` メソッドを公開して Lambda 関数を呼び出し、入力をクエリ文字列パラメータとして渡します (`AWS Service` 統合)。

1. `POST` リソースで `/calc` メソッドを公開して Lambda 関数を呼び出すことにより、メソッドリクエストのペイロードに入力を提供します (`AWS Service` 統合)。

1. ネストされた `GET` リソースで `/calc/{operand1}/{operand2}/{operator}` を公開して Lambda 関数を呼び出し、パスパラメータとして入力を提供します (`Lambda Function` 統合)。

このチュートリアルを試してみるだけでなく、`Calc` API 用の [OpenAPI 定義ファイル](api-as-lambda-proxy-export-swagger-with-extensions.md)を検討することをお勧めします。これは、[API Gateway で OpenAPI を使用して REST API を開発する](api-gateway-import-api.md) の API Gateway へのインポートの指示に従ってインポートできます。

**Topics**
+ [引き受け可能な IAM ロールを作成する](#api-as-lambda-proxy-setup-iam-role-policies)
+ [`Calc` Lambda 関数の作成](#api-as-lambda-proxy-create-lambda-function)
+ [`Calc` Lambda 関数をテストする](#api-as-lambda-proxy-test-lambda-function-)
+ [`Calc` API を作成する](#api-as-lambda-proxy-create-api-resources)
+ [統合 1: Lambda 関数を呼び出すためのクエリパラメータを持つ `GET` メソッドを作成する](#api-as-lambda-proxy-expose-get-method-with-query-strings-to-call-lambda-function)
+ [統合 2: Lambda 関数を呼び出すための JSON ペイロードを持つ `POST` メソッドを作成する](#api-as-lambda-proxy-expose-post-method-with-json-body-to-call-lambda-function)
+ [統合 3: Lambda 関数を呼び出すためのパスパラメータを持つ `GET` メソッドを作成する](#api-as-lambda-proxy-expose-get-method-with-path-parameters-to-call-lambda-function)
+ [Lambda 関数と統合されたサンプル API の OpenAPI 定義](api-as-lambda-proxy-export-swagger-with-extensions.md)

## 引き受け可能な IAM ロールを作成する
<a name="api-as-lambda-proxy-setup-iam-role-policies"></a>

API で `Calc` Lambda 関数を呼び出すには、API Gateway が引き受け可能な IAM ロールが必要です。これは、次の信頼関係を持つ IAM ロールです。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

作成するロールには Lambda [InvokeFunction](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html) アクセス許可が必要です。それ以外の場合、API 発信者は `500 Internal Server Error` レスポンスを受け取ります。このアクセス許可をロールに付与するには、次の IAM ポリシーをアタッチします。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "*"
        }
    ]
}
```

------

これをすべて実行する方法は次のとおりです。

**API Gateway の引き受け可能な IAM ロールを作成する**

1. IAM コンソールにログインします。

1. [**Roles (ロール)**] を選択します。

1. [**Create Role (ロールの作成)**] を選択します。

1. [**Select type of trusted entity**] (信頼されたエンティティの種類を選択) の下で、[**AWS Service**] (サービス) を選択します。

1. [**このロールを使用するサービスを選択**] の下で、[**Lambda**] を選択します。

1. [**Next: Permissions (次へ: アクセス許可)**] を選択します。

1. [**ポリシーの作成**] を選択します。

   新しい [**ポリシーの作成**] コンソールウィンドウが開きます。このウィンドウで、以下の操作を行います。

   1. [**JSON**] タブで、既存のポリシーを以下のポリシーに置き換えます。

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "lambda:InvokeFunction",
                  "Resource": "*"
              }
          ]
      }
      ```

------

   1. [**ポリシーの確認**] を選択します。

   1. [**ポリシーの確認**] で、以下の作業を行います。

      1. [**名前**] には **lambda\$1execute** などの名前を入力します。

      1. [**ポリシーの作成**] を選択します。

1. 元の [**ロールの作成**] ウィンドウで、以下の操作を行います。

   1. [**アクセス権限ポリシーをアタッチする**] で、ドロップダウンリストから **lambda\$1execute** ポリシーを選択します。

      ポリシーが一覧に表示されていない場合は、一覧の上部にある [refresh (更新)] ボタンをクリックしてください。(ブラウザページを更新しないでください)。

   1. [**Next:Tags (次へ: タグ)**] を選択します。

   1. [**次のステップ: 確認**] を選択します。

   1. [**ロール名**] には、**lambda\$1invoke\$1function\$1assume\$1apigw\$1role** などの名前を入力します。

   1. [**ロールの作成**] を選択します。

1. ロールのリストから **lambda\$1invoke\$1function\$1assume\$1apigw\$1role** 関数を選択します。

1. [**信頼関係**] タブを選択します。

1. [**Edit trust relationship (信頼関係の編集)**] を選択します。

1. 既存のポリシーを以下に置き換えます。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Sid": "",
         "Effect": "Allow",
         "Principal": {
           "Service": [
             "lambda.amazonaws.com",
             "apigateway.amazonaws.com"
           ]
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

------

1. [**Update Trust Policy**] を選択します。

1. 作成したロールのロール ARN を書き留めます。後で必要になります。

## `Calc` Lambda 関数の作成
<a name="api-as-lambda-proxy-create-lambda-function"></a>

次に、 Lambda コンソールを使用して Lambda 関数を作成します。

1. Lambda コンソールで、[**Create function (関数の作成)**] をクリックします。

1. [**一から作成**] を選択します。

1. [**名前**] に「**Calc**」と入力します。

1. **[ランタイム]** で、サポートされている最新の **Node.js** または **Python** ランタイムのいずれかを選択します。

1. 他のすべてのオプションについては、デフォルトの設定を使用します。

1. [**関数の作成**] を選択してください。

1.  任意のランタイムで以下の Lambda 関数をコピーし、Lambda コンソールのコードエディターに貼り付けます。

------
#### [ Node.js ]

   ```
   export const handler = async function (event, context) {
     console.log("Received event:", JSON.stringify(event));
   
     if (
       event.a === undefined ||
       event.b === undefined ||
       event.op === undefined
     ) {
       return "400 Invalid Input";
     }
   
     const res = {};
     res.a = Number(event.a);
     res.b = Number(event.b);
     res.op = event.op;
     if (isNaN(event.a) || isNaN(event.b)) {
       return "400 Invalid Operand";
     }
     switch (event.op) {
       case "+":
       case "add":
         res.c = res.a + res.b;
         break;
       case "-":
       case "sub":
         res.c = res.a - res.b;
         break;
       case "*":
       case "mul":
         res.c = res.a * res.b;
         break;
       case "/":
       case "div":
         if (res.b == 0) {
           return "400 Divide by Zero";
         } else {
           res.c = res.a / res.b;
         }
         break;
       default:
         return "400 Invalid Operator";
     }
   
     return res;
   };
   ```

------
#### [ Python ]

   ```
   import json
   
   
   def lambda_handler(event, context):
       print(event)
   
       try:
           (event['a']) and (event['b']) and (event['op'])
       except KeyError:
           return '400 Invalid Input'
   
       try:
           res = {
               "a": float(
                   event['a']), "b": float(
                   event['b']), "op": event['op']}
       except ValueError:
           return '400 Invalid Operand'
   
       if event['op'] == '+':
           res['c'] = res['a'] + res['b']
       elif event['op'] == '-':
           res['c'] = res['a'] - res['b']
       elif event['op'] == '*':
           res['c'] = res['a'] * res['b']
       elif event['op'] == '/':
           if res['b'] == 0:
               return '400 Divide by Zero'
           else:
               res['c'] = res['a'] / res['b']
       else:
           return '400 Invalid Operator'
   
       return res
   ```

------

1. 実行ロールで、[**Choose an existing role (既存のロールを選択)**] を選択します。

1. 前に作成した **lambda\$1invoke\$1function\$1assume\$1apigw\$1role** ロールのロール ARN を入力します。

1. [**デプロイ**] を選択します。

 この関数には、`a` 入力パラメータからの 2 つのオペランド (`b` と `op`) および演算子 (`event`) が必要です。入力は以下の形式の JSON オブジェクトです。

```
{
  "a": "Number" | "String",
  "b": "Number" | "String",
  "op": "String"
}
```

この関数は計算結果 (`c`) と入力を返します。入力が無効な場合、関数は結果として Null 値または「Invalid op」文字列のいずれかを返します。出力は以下の JSON 形式になります。

```
{
  "a": "Number",
  "b": "Number",
  "op": "String",
  "c": "Number" | "String"
}
```

この関数は、次のステップで API と統合する前に、Lambda コンソールでテストする必要があります。

## `Calc` Lambda 関数をテストする
<a name="api-as-lambda-proxy-test-lambda-function-"></a>

これが、Lambda コンソールで `Calc` 関数をテストする方法です。

1. **[テスト]** タブを選択します。

1. テストイベントの名前として **calc2plus5** と入力します。

1. テストイベントの定義を次のように置き換えます。

   ```
   {
     "a": "2",
     "b": "5",
     "op": "+"
   }
   ```

1. [**保存**] を選択します。

1. [**Test (テスト)**] を選択します。

1. [**実行結果: 成功**] を展開します。次のように表示されます。

   ```
   {
     "a": 2,
     "b": 5,
     "op": "+",
     "c": 7
   }
   ```

## `Calc` API を作成する
<a name="api-as-lambda-proxy-create-api-resources"></a>

次の手順は、作成したばかりの `Calc` Lambda 関数用の API を作成する方法を示しています。次のセクションでは、リソースとメソッドをそれに追加します。

**API を作成するには**

1. [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway) で API Gateway コンソールにサインインします。

1. API Gateway を初めて使用する場合は、サービスの特徴を紹介するページが表示されます。[**REST API**] で、[**構築**] を選択します。[**Create Example API (サンプル API の作成)**] がポップアップ表示されたら、[**OK**] を選択します。

   API Gateway を使用するのが初めてではない場合、[**Create API**] (API を作成)を選択します。[**REST API**] で、[**構築**] を選択します。

1.  [**API 名**] に「**LambdaCalc**」と入力します。

1. (オプション) **[説明]** に説明を入力します。

1. **[API エンドポイントタイプ]** を **[リージョン別]** に設定したままにします。

1. **[IP アドレスの種類]** には **[IPv4]** を選択します。

1. [**Create API**] を選択します。

## 統合 1: Lambda 関数を呼び出すためのクエリパラメータを持つ `GET` メソッドを作成する
<a name="api-as-lambda-proxy-expose-get-method-with-query-strings-to-call-lambda-function"></a>

クエリ文字列パラメータを Lambda 関数に渡す `GET` メソッドを作成することで、ブラウザから API を呼び出すことができます。この方法は、特にオープンアクセスを許可する API には便利です。

API を作成したら、リソースを作成します。通常、API リソースはアプリケーションロジックに従ってリソースツリーに整理されます。このステップでは、**/calc** リソースを作成します。

****/calc** リソースを作成するには**

1. **[リソースの作成]** を選択します。

1. **[プロキシのリソース]** はオフのままにします。

1. **[リソースパス]** は `/` のままにします。

1. **[リソース名]** に「**calc**」と入力します。

1. **[CORS (Cross Origin Resource Sharing)]** はオフのままにします。

1. **[リソースの作成]** を選択します。

クエリ文字列パラメータを Lambda 関数に渡す `GET` メソッドを作成することで、ブラウザから API を呼び出すことができます。この方法は、特にオープンアクセスを許可する API には便利です。

このメソッドの場合、Lambda は、すべての Lambda 関数の呼び出しに `POST` リクエストを使用することを要求します。この例では、フロントエンドのメソッドリクエストの HTTP メソッドは、バックエンドの統合リクエストとは異なる場合があることを示しています。

**`GET` メソッドを作成するには**

1. **/calc** リソースを選択し、**[メソッドを作成]** を選択します。

1. **[メソッドタイプ]** には、**GET** を選択します。

1. **[統合タイプ]** で、**[AWS のサービス]** を選択します。

1. **[AWS リージョン]** で、Lambda 関数を作成した AWS リージョンを選択します。

1. **[AWS のサービス]** で、**[Lambda]** を選択します。

1. **[AWS サブドメイン]** は空白のままにします。

1. **[HTTP メソッド]** で、**[POST]** を選択します。

1. **[アクションタイプ]** で、**[パスオーバーライドを使用]** を選択します。このオプションでは、実行する [Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) アクションの ARN を指定して `Calc` 関数を呼び出すことができます。

1. **[パスオーバーライド]** に「**2015-03-31/functions/arn:aws:lambda:*us-east-2*:*account-id*:function:Calc/invocations**」と入力します。[** *account-id***] に AWS アカウント ID を入力します。[***us-east-2***] に、Lambda 関数を作成した AWS リージョンを入力します。

1. **[実行ロール]** に、**lambda\$1invoke\$1function\$1assume\$1apigw\$1role** のロール ARN を入力します。

1. **[認証情報キャッシュ]** と **[デフォルトタイムアウト]** の設定は変更しません。

1. **[メソッドリクエストの設定]** を選択します。

1. **[リクエストの検証]** で、**[クエリ文字列パラメータおよびヘッダーを検証]** を選択します。

   この設定により、クライアントが必要なパラメータを指定しなかった場合に、エラーメッセージが返されます。

1. **[URL クエリ文字列パラメータ]** を選択します。

   次に、**[/calc]** リソースで **GET** メソッドのクエリ文字列パラメータを設定し、バックエンドの Lambda 関数に代わって入力を受け取れるようにします。

   クエリ文字列パラメータを作成するには、次の操作を行います。

   1. [**クエリ文字列の追加**] を選択します。

   1. **[Name]** (名前) には **operand1** を入力します。

   1. **[必須]** をオンにします。

   1. **[キャッシュ]** はオフのままにします。

   同じ手順を繰り返して、**operand2** という名前のクエリ文字列と **operator** という名前のクエリ文字列を作成します。

1. **[メソッドの作成]** を選択します。

次に、`Calc` 関数の要求に応じて、クライアントが指定したクエリ文字列を統合リクエストのペイロードに変換するためのマッピングテンプレートを作成します。このテンプレートでは、**[メソッドリクエスト]** で宣言した 3 つのクエリ文字列パラメータを、JSON オブジェクトの指定したプロパティ値にマッピングし、バックエンドの Lambda 関数への入力として使用します。変換された JSON オブジェクトは統合リクエストのペイロードとして含まれます。

**入力パラメータを統合リクエストにマッピングするには**

1. **[統合リクエスト]** タブの **[統合リクエストの設定]** で、**[編集]** を選択します。

1. **[リクエスト本文のパススルー]** で、**[テンプレートが定義されていない場合 (推奨)]** を選択します。

1. **[マッピングテンプレート]** を選択します。

1. [**マッピングテンプレートの追加**] を選択します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

1. **[テンプレート本文]** に、次のコードを入力します。

   ```
   {
       "a":  "$input.params('operand1')",
       "b":  "$input.params('operand2')", 
       "op": "$input.params('operator')"   
   }
   ```

1. **[保存]** を選択します。

これで、`GET` メソッドをテストして、このメソッドが Lambda 関数を呼び出すように適切に設定されていることを確認できます。

**`GET` メソッドをテストするには**

1. **[テスト]** タブを選択します。タブを表示するには、右矢印ボタンを選択する必要がある場合があります。

1. **[クエリ文字列]** に「**operand1=2&operand2=3&operator=\$1**」と入力します

1. [**Test (テスト)**] を選択します。

   結果は以下のようになります。  
![\[API Gateway で Lambda プロキシとして API を作成する\]](http://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/images/aws_proxy_lambda_calc_get_method_test_new_console.png)

## 統合 2: Lambda 関数を呼び出すための JSON ペイロードを持つ `POST` メソッドを作成する
<a name="api-as-lambda-proxy-expose-post-method-with-json-body-to-call-lambda-function"></a>

Lambda 関数を呼び出すための JSON ペイロードを含む `POST` メソッドを作成することによって、クライアントがリクエストボディのバックエンド関数に必要な入力を提供するようにします。クライアントが正しい入力データをアップロードしたことを確認するために、ペイロードに対してリクエストの検証を有効にします。

**JSON ペイロードを持つ `POST` メソッドを作成するには**

1. **/calc** リソースを選択し、**[メソッドを作成]** を選択します。

1. **[メソッドタイプ]** では、**POST** を選択します。

1. **[統合タイプ]** で、**[AWS のサービス]** を選択します。

1. **[AWS リージョン]** で、Lambda 関数を作成した AWS リージョンを選択します。

1. **[AWS のサービス]** で、**[Lambda]** を選択します。

1. **[AWS サブドメイン]** は空白のままにします。

1. **[HTTP メソッド]** で、**[POST]** を選択します。

1. **[アクションタイプ]** で、**[パスオーバーライドを使用]** を選択します。このオプションでは、実行する [Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) アクションの ARN を指定して `Calc` 関数を呼び出すことができます。

1. **[パスオーバーライド]** に「**2015-03-31/functions/arn:aws:lambda:*us-east-2*:*account-id*:function:Calc/invocations**」と入力します。[** *account-id***] に AWS アカウント ID を入力します。[***us-east-2***] に、Lambda 関数を作成した AWS リージョンを入力します。

1. **[実行ロール]** に、**lambda\$1invoke\$1function\$1assume\$1apigw\$1role** のロール ARN を入力します。

1. **[認証情報キャッシュ]** と **[デフォルトタイムアウト]** の設定は変更しません。

1. **[メソッドの作成]** を選択します。

次に、入力データ構造を記述して受信リクエスト本文を検証するための **[入力]** モデルを作成します。

**入力モデルを作成するには**

1. ナビゲーションペインで、**[モデル]** を選択します。

1. **[モデルの作成]** を選択します。

1. **[Name]** (名前) には **input** を入力します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

   一致するコンテンツタイプが見つからない場合、リクエストの検証は実行されません。コンテンツタイプに関係なく同じモデルを使用するには、「**\$1default**」と入力します。

1. **[モデルのスキーマ]** に次のモデルを入力します。

   ```
   {
       "type":"object",
       "properties":{
           "a":{"type":"number"},
           "b":{"type":"number"},
           "op":{"type":"string"}
       },
       "title":"input"
   }
   ```

1. **[モデルの作成]** を選択します。

次に、**[出力]** モデルを作成します。このモデルでは、バックエンドの計算結果のデータ構造を記述します。このモデルを使用して統合レスポンスデータを別のモデルにマッピングできます。このチュートリアルではパススルー動作を利用するため、このモデルは使用しません。

**出力モデルを作成するには**

1. **[モデルの作成]** を選択します。

1. **[Name]** (名前) には **output** を入力します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

   一致するコンテンツタイプが見つからない場合、リクエストの検証は実行されません。コンテンツタイプに関係なく同じモデルを使用するには、「**\$1default**」と入力します。

1. **[モデルのスキーマ]** に次のモデルを入力します。

   ```
   {
       "type":"object",
       "properties":{
           "c":{"type":"number"}
       },
       "title":"output"
   }
   ```

1. **[モデルの作成]** を選択します。

次に、**[結果]** モデルを作成します。このモデルでは、返されたレスポンスデータのデータ構造を記述します。これは、API で定義されている **[入力]** スキーマと **[出力]** スキーマの両方を参照します。

**結果モデルを作成するには**

1. **[モデルの作成]** を選択します。

1. **[Name]** (名前) には **result** を入力します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

   一致するコンテンツタイプが見つからない場合、リクエストの検証は実行されません。コンテンツタイプに関係なく同じモデルを使用するには、「**\$1default**」と入力します。

1. **[モデルスキーマ]** に、*restapi-id* を使用して、次のモデルを入力します。*restapi-id* はコンソールの上部に、このフロー (`API Gateway > APIs > LambdaCalc (abc123).`) で括弧内に表示されます。

   ```
   {
       "type":"object",
       "properties":{
           "input":{
               "$ref":"https://apigateway.amazonaws.com/restapis/restapi-id/models/input"
           },
           "output":{
               "$ref":"https://apigateway.amazonaws.com/restapis/restapi-id/models/output"
           }
       },
       "title":"result"
   }
   ```

1. **[モデルの作成]** を選択します。

次に、受信リクエスト本文に対するリクエストの検証を有効にする POST メソッドのメソッドリクエストを設定します。

**POST メソッドのリクエスト検証を有効にするには**

1. メインナビゲーションペインで **[リソース]** を選択し、リソースツリーの `POST` メソッドを選択します。

1. **[メソッドリクエスト]** タブの **[メソッドリクエスト設定]** で、**[編集]** を選択します。

1. **[リクエストの検証]** で、**[本文を検証]** を選択します。

1. **[リクエスト本文]** を選択し、**[モデルを追加]** を選択します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

   一致するコンテンツタイプが見つからない場合、リクエストの検証は実行されません。コンテンツタイプに関係なく同じモデルを使用するには、「**\$1default**」と入力します。

1. **[モデル]** で **[入力]** を選択します。

1. **[保存]** を選択します。

これで、`POST` メソッドをテストして、このメソッドが Lambda 関数を呼び出すように適切に設定されていることを確認できます。

**`POST` メソッドをテストするには**

1. **[テスト]** タブを選択します。タブを表示するには、右矢印ボタンを選択する必要がある場合があります。

1. **[リクエスト本文]** に次の JSON ペイロードを入力します。

   ```
   {
       "a": 1,
       "b": 2,
       "op": "+"
   }
   ```

1. **[テスト]** を選択します。

   以下の出力が表示されます。

   ```
   {
     "a": 1,
     "b": 2,
     "op": "+",
     "c": 3
   }
   ```

## 統合 3: Lambda 関数を呼び出すためのパスパラメータを持つ `GET` メソッドを作成する
<a name="api-as-lambda-proxy-expose-get-method-with-path-parameters-to-call-lambda-function"></a>

次に、一連のパスパラメータで指定されたリソースで `GET` メソッドを作成し、バックエンドの Lambda 関数を呼び出します。パスパラメータの値は、Lambda 関数への入力データを指定します。受信パスパラメータ値を必要な統合リクエストペイロードにマッピングするためのマッピングテンプレートを使用します。

生成された API リソースの構造は次のようになります。

![\[API Gateway で Lambda プロキシとして API を作成する\]](http://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/images/aws_proxy_lambda_create_api_resources_new_console.png)


****/\$1operand1\$1/\$1operand2\$1/\$1operator\$1** リソースを作成するには**

1. **[リソースの作成]** を選択します。

1. **[リソースパス]** で、`/calc` を選択します。

1. **[リソース名]** に「**\$1operand1\$1**」と入力します。

1. **[CORS (Cross Origin Resource Sharing)]** はオフのままにします。

1. **[リソースの作成]** を選択します。

1. **[リソースパス]** で、`/calc/{operand1}/` を選択します。

1. **[リソース名]** に「**\$1operand2\$1**」と入力します。

1. **[CORS (Cross Origin Resource Sharing)]** はオフのままにします。

1. **[リソースの作成]** を選択します。

1. **[リソースパス]** で、`/calc/{operand1}/{operand2}/` を選択します。

1. **[リソース名]** に「**\$1operator\$1**」と入力します。

1. **[CORS (Cross Origin Resource Sharing)]** はオフのままにします。

1. **[リソースの作成]** を選択します。

今回は、API Gateway コンソールに組み込まれている Lambda 統合を使用してメソッド統合を設定します。

**メソッド統合を設定するには**

1. **/\$1operand1\$1/\$1operand2\$1/\$1operator\$1** を選択し、**[メソッドを作成]** を選択します。

1. **[メソッドタイプ]** には、**GET** を選択します。

1. **[統合タイプ]** で、**[Lambda 関数]** を選択します。

1. **[Lambda プロキシ統合]** はオフのままにしておきます。

1. **[Lambda 関数]** で、Lambda 関数を作成した AWS リージョンを選択し、「**Calc**」と入力します。

1. **[デフォルトタイムアウト]** はオンのままにします。

1. **[メソッドの作成]** を選択します。

次に、マッピングテンプレートを作成し、**/calc/\$1operand1\$1/\$1operand2\$1/\$1operator\$1** リソースの作成時に宣言した 3 つの URL パスパラメータを、JSON オブジェクトで指定したプロパティ値にマッピングします。URL パスは URL エンコードされる必要があるため、除算演算子を `%2F` ではなく `/` として指定してください。このテンプレート では、`%2F` を `'/'` に変換してから Lambda 関数に渡します。

**マッピングテンプレートを作成するには**

1. **[統合リクエスト]** タブの **[統合リクエストの設定]** で、**[編集]** を選択します。

1. **[リクエスト本文のパススルー]** で、**[テンプレートが定義されていない場合 (推奨)]** を選択します。

1. **[マッピングテンプレート]** を選択します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

1. **[テンプレート本文]** に、次のコードを入力します。

   ```
   {
      "a": "$input.params('operand1')",
      "b": "$input.params('operand2')",
      "op": #if($input.params('operator')=='%2F')"/"#{else}"$input.params('operator')"#end
   }
   ```

1. **[保存]** を選択します。

これで、`GET` メソッドをテストし、このメソッドが Lambda 関数を呼び出して、マッピングなしで統合レスポンスを介して元の出力を渡すように適切に設定されていることを確認できます。

**`GET` メソッドをテストするには**

1. **[テスト]** タブを選択します。タブを表示するには、右矢印ボタンを選択する必要がある場合があります。

1. **[パス]** で、次の操作を行います。

   1. **[operand1]** に「**1**」と入力します。

   1. **[operand2]** に「**1**」と入力します。

   1. **[operator]** に「**\$1**」と入力します。

1. [**Test (テスト)**] を選択します。

1. 結果は以下のようになります。  
![\[API Gateway コンソールで GET メソッドをテストします。\]](http://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/images/aws_proxy_lambda_calc_get_method_test_path_parm_new_console.png)

次に、`result` スキーマに従って、メソッドレスポンスペイロードのデータ構造をモデル化します。

デフォルトでは、メソッドレスポンス本文に空のモデルが割り当てられます。これにより、統合レスポンス本文がマッピングなしで渡されます。ただし、Java や Objective-C などの厳密に型指定された言語のいずれかの SDK を生成すると、SDK ユーザーは空のオブジェクトを結果として受け取ります。REST クライアントと SDK クライアントの両方が必要な結果を受け取るためには、事前定義済みのスキーマを使用してレスポンスデータをモデル化する必要があります。ここでは、メソッドレスポンス本文のモデルを定義し、マッピングテンプレートを構築して統合レスポンス本文をメソッドレスポンス本文に変換します。

**メソッドレスポンスを作成するには**

1. **[メソッドレスポンス]** タブの **[レスポンス 200]** で、**[編集]** を選択します。

1. **[リクエスト本文]** で、**[モデルを追加]** を選択します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

1. **[モデル]** で、**[結果]** を選択します。

1. **[保存]** を選択します。

メソッドレスポンス本文のモデルを設定すると、レスポンスデータは該当する SDK の `result` オブジェクトにキャストされます。それに応じて統合レスポンスデータが確実にマッピングされるようにするには、マッピングテンプレートが必要です。

**マッピングテンプレートを作成するには**

1. **[統合レスポンス]** タブの **[デフォルト - レスポンス]** で、**[編集]** を選択します。

1. **[マッピングテンプレート]** を選択します。

1. **[コンテンツタイプ]** に、「**application/json**」と入力します。

1. **[テンプレート本文]** に、次のコードを入力します。

   ```
   #set($inputRoot = $input.path('$'))
   {
     "input" : {
       "a" : $inputRoot.a,
       "b" : $inputRoot.b,
       "op" : "$inputRoot.op"
     },
     "output" : {
       "c" : $inputRoot.c
     }
   }
   ```

1. **[保存]** を選択します。

**マッピングテンプレートをテストするには**

1. **[テスト]** タブを選択します。タブを表示するには、右矢印ボタンを選択する必要がある場合があります。

1. **[パス]** で、次の操作を行います。

   1. **[operand1]** に「**1**」と入力します。

   1. **[operand2]** に「**2**」と入力します。

   1. **[operator]** に「**\$1**」と入力します。

1. **[テスト]** を選択します。

1. 結果は次のようになります。

   ```
   {
     "input": {
       "a": 1,
       "b": 2,
       "op": "+"
     },
     "output": {
       "c": 3
     }
   }
   ```

この時点では、API Gateway コンソールの **[テスト]** 機能を使用してのみ API を呼び出すことができます。クライアントが利用できるようにするには、API をデプロイする必要があります。リソースやメソッドを追加、変更、削除したり、データマッピングを更新したり、ステージ設定を更新したりするときには、必ず API を再デプロイしてください。そうしないと、新しい機能やアップデートは API のクライアントに利用可能になりません。デプロイ手順は次のとおりです。

**API をデプロイする**

1. [**API のデプロイ**] を選択します。

1. **[ステージ]** で **[新規ステージ]** を選択します。

1. [**Stage name (ステージ名)**] に **Prod** と入力します。

1. (オプション) **[説明]** に説明を入力します。

1. **[デプロイ]** をクリックします。

1.  (オプション) **[ステージの詳細]** の **[呼び出し URL]** で、コピーアイコンを選択して API の呼び出し URL をコピーします。[Postman](https://www.postman.com) や [cURL](https://curl.se/) のようなツールでこれを使用して API をテストできます。

**注記**  
リソースやメソッドの追加、変更、削除、データマッピングの更新、ステージ設定の更新を行う場合は、必ず API を再デプロイします。そうしない場合、新しい機能やアップデートは API のクライアントには利用できません。

# Lambda 関数と統合されたサンプル API の OpenAPI 定義
<a name="api-as-lambda-proxy-export-swagger-with-extensions"></a>

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2017-04-20T04:08:08Z",
    "title": "LambdaCalc"
  },
  "host": "uojnr9hd57.execute-api.us-east-1.amazonaws.com",
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/calc": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "operand2",
            "in": "query",
            "required": true,
            "type": "string"
          },
          {
            "name": "operator",
            "in": "query",
            "required": true,
            "type": "string"
          },
          {
            "name": "operand1",
            "in": "query",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            },
            "headers": {
              "operand_1": {
                "type": "string"
              },
              "operand_2": {
                "type": "string"
              },
              "operator": {
                "type": "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator": "Validate query string parameters and headers",
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.operator": "integration.response.body.op",
                "method.response.header.operand_2": "integration.response.body.b",
                "method.response.header.operand_1": "integration.response.body.a"
              },
              "responseTemplates": {
                "application/json": "#set($res = $input.path('$'))\n{\n    \"result\": \"$res.a, $res.b, $res.op => $res.c\",\n  \"a\" : \"$res.a\",\n  \"b\" : \"$res.b\",\n  \"op\" : \"$res.op\",\n  \"c\" : \"$res.c\"\n}"
              }
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "requestTemplates": {
            "application/json": "{\n    \"a\":  \"$input.params('operand1')\",\n    \"b\":  \"$input.params('operand2')\", \n    \"op\": \"$input.params('operator')\"   \n}"
          },
          "type": "aws"
        }
      },
      "post": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "Input",
            "required": true,
            "schema": {
              "$ref": "#/definitions/Input"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-request-validator": "Validate body",
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"a\" : $inputRoot.a,\n  \"b\" : $inputRoot.b,\n  \"op\" : $inputRoot.op,\n  \"c\" : $inputRoot.c\n}"
              }
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_templates",
          "httpMethod": "POST",
          "type": "aws"
        }
      }
    },
    "/calc/{operand1}/{operand2}/{operator}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "operand2",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "operator",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "operand1",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_templates",
          "httpMethod": "POST",
          "requestTemplates": {
            "application/json": "{\n   \"a\": \"$input.params('operand1')\",\n   \"b\": \"$input.params('operand2')\",\n   \"op\": #if($input.params('operator')=='%2F')\"/\"#{else}\"$input.params('operator')\"#end\n   \n}"
          },
          "contentHandling": "CONVERT_TO_TEXT",
          "type": "aws"
        }
      }
    }
  },
  "definitions": {
    "Input": {
      "type": "object",
      "required": [
        "a",
        "b",
        "op"
      ],
      "properties": {
        "a": {
          "type": "number"
        },
        "b": {
          "type": "number"
        },
        "op": {
          "type": "string",
          "description": "binary op of ['+', 'add', '-', 'sub', '*', 'mul', '%2F', 'div']"
        }
      },
      "title": "Input"
    },
    "Output": {
      "type": "object",
      "properties": {
        "c": {
          "type": "number"
        }
      },
      "title": "Output"
    },
    "Result": {
      "type": "object",
      "properties": {
        "input": {
          "$ref": "#/definitions/Input"
        },
        "output": {
          "$ref": "#/definitions/Output"
        }
      },
      "title": "Result"
    }
  },
  "x-amazon-apigateway-request-validators": {
    "Validate body": {
      "validateRequestParameters": false,
      "validateRequestBody": true
    },
    "Validate query string parameters and headers": {
      "validateRequestParameters": true,
      "validateRequestBody": false
    }
  }
}
```

------