

# チュートリアル: AWS サービスへの統合のための統合リクエストとレスポンスを変更する
<a name="set-up-data-transformations-in-api-gateway"></a>

次のチュートリアルでは、マッピングテンプレート変換を使用して、コンソールと AWS CLI で統合リクエストとレスポンスを変換するためのマッピングテンプレートを設定する方法を説明します。

**Topics**
+ [API Gateway コンソールを使用してデータ変換を設定する](#mapping-example-console)
+ [AWS CLI を使用してデータ変換を設定する](#mapping-example-cli)
+ [完成したデータ変換の CloudFormation テンプレート](#api-gateway-data-transformations-full-cfn-stack)

## API Gateway コンソールを使用してデータ変換を設定する
<a name="mapping-example-console"></a>

このチュートリアルでは、.zip ファイル ([data-transformation-tutorial-console.zip](samples/data-transformation-tutorial-console.zip)) を使用して不完全な API と DynamoDB テーブルを作成します。この不完全な API には、`GET` メソッドと `POST` メソッドを持つ `/pets` リソースがあります。
+ `GET` メソッドは `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP エンドポイントからデータを取得します。出力データは、[API Gateway での REST API のテンプレート変換のマッピング](models-mappings.md) のマッピングテンプレートに従って変換されます。
+ `POST` メソッドを使用すると、ユーザーはマッピングテンプレートを使用して Amazon DynamoDB テーブルにペット情報を `POST` できます。

[CloudFormation のアプリケーション作成テンプレート](samples/data-transformation-tutorial-console.zip)をダウンロードして解凍します。このテンプレートを使用して、ペット情報と不完全な API を投稿するための DynamoDB テーブルを作成します。残りのステップは API Gateway コンソールで完了します。

**CloudFormation スタックを作成するには**

1. [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) で CloudFormation コンソール を開きます。

1. [**スタックの作成**] を選択し、[**With new resources (standard) 新しいリソースを使用 (標準)**] を選択します。

1. [**Specify template (テンプレートの指定)**] で、[**Upload a template file (テンプレートファイルのアップロード)**] を選択します。

1. ダウンロードしたテンプレートを選択します。

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

1. [**Stack name**] (スタックの名前) で、**data-transformation-tutorial-console** と入力し、[**Next**] (次へ) を選択します。

1. [**Configure stack options**] (スタックオプションの設定) で、[**Next**] (次へ) を選択します。

1. [**Capabilities**] (機能) で、CloudFormation がアカウントに IAM リソースを作成できることを承認します。

1. **[次へ]** を選択し、**[送信]** を選択します。

CloudFormation は、テンプレートで指定されたリソースをプロビジョニングします。リソースのプロビジョニングには数分かかることがあります。CloudFormation スタックのステータスが **CREATE\$1COMPLETE** の場合は、次のステップに進む準備ができています。

**`GET` 統合レスポンスをテストするには**

1. **data-transformation-tutorial-console** の CloudFormation スタックの **[リソース]** タブで、API の物理 ID を選択します。

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

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

   テストの出力には、次の内容が表示されます。

   ```
   [
     {
       "id": 1,
       "type": "dog",
       "price": 249.99
     },
     {
       "id": 2,
       "type": "cat",
       "price": 124.99
     },
     {
       "id": 3,
       "type": "fish",
       "price": 0.99
     }
   ]
   ```

   この出力を [API Gateway での REST API のテンプレート変換のマッピング](models-mappings.md) のマッピングテンプレートに従って変換します。

**`GET` 統合レスポンスを変換するには**

1. **[統合レスポンス]** タブを選択します。

   現在、マッピングテンプレートは定義されていないため、統合レスポンスは変換されません。

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

1. **[マッピングテンプレート]** を選択し、次の操作を行います。

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

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

   1. **[テンプレート本文]** で次のように入力します。

      ```
      #set($inputRoot = $input.path('$'))
      [
      #foreach($elem in $inputRoot)
        {
          "description" : "Item $elem.id is a $elem.type.",
          "askingPrice" : $elem.price
        }#if($foreach.hasNext),#end
      
      #end
      ]
      ```

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

**`GET` 統合レスポンスをテストするには**
+ **[テスト]** タブ、**[テスト]** の順に選択します。

  テストの出力に、変換されたレスポンスが表示されます。

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**`POST` メソッドからの入力データを変換するには**

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

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

   CloudFormation テンプレートでは、いくつかの統合リクエストフィールドが入力されています。
   +  統合タイプは AWS のサービスです。
   +  AWS のサービスは DynamoDB です。
   +  HTTP メソッドは `POST` です。
   +  アクションは `PutItem` です。
   +  API Gateway が DynamoDB テーブルに項目を入力できるようにする実行ロールは `data-transformation-tutorial-console-APIGatewayRole` です。CloudFormation は、API Gateway が DynamoDB とやり取りするための最小限のアクセス許可を持つように、このロールを作成済みです。

    DynamoDB テーブルの名前は未指定です。次の手順に従って名前を指定します。

1. **[リクエスト本文のパススルー]** で、**[なし]** を選択します。

   つまり、API はマッピングテンプレートを持たない Content-Type のデータを拒否します。

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

1. **[コンテンツタイプ]** は `application/json` に設定されます。つまり、application/json 以外のコンテンツタイプは API によって拒否されます。統合パススルーの動作の詳細については、「[API Gateway で REST API のマッピングテンプレートを使用しないペイロードのメソッドリクエストの動作](integration-passthrough-behaviors.md)」を参照してください。

1. テキストエディタに次のコードを入力します。

   ```
   {
       "TableName":"data-transformation-tutorial-console-ddb",
       "Item": {
           "id": {
               "N": $input.json("$.id")
           },
           "type": {
               "S": $input.json("$.type")
           },
           "price": {
               "N": $input.json("$.price")
           }
       }
   }
   ```

    このテンプレートでは、テーブルを `data-transformation-tutorial-console-ddb` として指定し、項目を `id`、`type`、`price` として設定します。項目は、`POST` メソッドの本体から取得されます。データモデルを使用してマッピングテンプレートを作成することもできます。詳細については、「[API Gateway での REST API のリクエスト検証](api-gateway-method-request-validation.md)」を参照してください。

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

**`POST` メソッドからメソッドと統合レスポンスを追加するには**

CloudFormation は、空白のメソッドと統合レスポンスを作成済みです。このレスポンスを編集して詳細情報を入力します。レスポンスの編集方法の詳細については、「[API Gateway での REST API パラメータマッピングの例](request-response-data-mappings.md)」を参照してください。

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

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

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

1. コードエディタで、次の出力マッピングテンプレートを入力し、出力メッセージを送信します。

   ```
   { "message" : "Your response was recorded at $context.requestTime" }
   ```

   コンテキスト変数の詳細については、「[データ変換のコンテキスト変数](api-gateway-mapping-template-reference.md#context-variable-reference)」を参照してください。

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

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

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

1. リクエスト本文に、次の例を入力します。

   ```
   {
             "id": "4",
             "type" : "dog",
             "price": "321"
   }
   ```

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

   出力に成功メッセージが表示されるはずです。

    DynamoDB コンソール ([https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)) を開いて、サンプル項目がテーブルにあることを確認できます。

**CloudFormation スタックを削除するには**

1. CloudFormation コンソール ([https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)) を開きます。

1. CloudFormation スタックを選択します。

1. [**Delete**] (削除) を選択し、選択を確定します。

## AWS CLI を使用してデータ変換を設定する
<a name="mapping-example-cli"></a>

このチュートリアルでは、.zip ファイル ([data-transformation-tutorial-cli.zip](samples/data-transformation-tutorial-cli.zip)\$1 を使用して不完全な API と DynamoDB テーブルを作成します。この不完全な API には、`http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP エンドポイントと統合された `GET` メソッドを持つ `/pets` リソースがあります。`POST` メソッドを作成して DynamoDB テーブルに接続し、マッピングテンプレートを使用して DynamoDB テーブルにデータを入力します。
+ 出力データは、[API Gateway での REST API のテンプレート変換のマッピング](models-mappings.md) のマッピングテンプレートに従って変換します。
+ `POST` メソッドを作成し、ユーザーがマッピングテンプレートを使用して Amazon DynamoDB テーブルにペット情報を `POST` できるようにします。

**CloudFormation スタックを作成するには**

[CloudFormation のアプリケーション作成テンプレート](samples/data-transformation-tutorial-cli.zip)をダウンロードして解凍します。

次のチュートリアルを完了するには、[AWS Command Line Interface (AWS CLI) バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) が必要です。

コマンドが長い場合は、エスケープ文字 (`\`) を使用してコマンドを複数行に分割します。
**注記**  
Windows では、一般的に使用する Bash CLI コマンドの一部 (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://learn.microsoft.com/en-us/windows/wsl/install)します。このガイドの CLI コマンドの例では、Linux フォーマットを使用しています。Windows CLI を使用している場合、インライン JSON ドキュメントを含むコマンドを再フォーマットする必要があります。

1.  次のコマンドを使用して CloudFormation スタックを作成します。

   ```
   aws cloudformation create-stack --stack-name data-transformation-tutorial-cli --template-body file://data-transformation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation は、テンプレートで指定されたリソースをプロビジョニングします。リソースのプロビジョニングには数分かかることがあります。次のコマンドを使用して CloudFormation スタックのステータスを確認します。

   ```
   aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli
   ```

1. CloudFormation スタックのステータスが `StackStatus: "CREATE_COMPLETE"` になったら、次のコマンドを使用して関連する出力値を取得し、以後のステップで使用します。

   ```
    aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   出力値は以下のとおりです。
   + ApiRole。API Gateway が DynamoDB テーブルに項目を配置できるようにするロールの名前です。このチュートリアルの場合、ロール名は `data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG` です。
   + DDBTableName。DynamoDB テーブルの名前です。このチュートリアルの場合、インスタンス名は `data-transformation-tutorial-cli-ddb` です。
   + ResourceId。`GET` メソッドと `POST` メソッドを公開するペットリソースの ID です。このチュートリアルの場合、リソース ID は `efg456` です。
   + ApiId。API の ID です。このチュートリアルの場合、API の ID は `abc123` です。

**データ変換の前に `GET` メソッドをテストするには**
+ 次のコマンドを使用して、`GET` メソッドをテストします。

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
            --resource-id efg456 \
            --http-method GET
  ```

  テストの出力には、次の内容が表示されます。

  ```
  [
    {
      "id": 1,
      "type": "dog",
      "price": 249.99
    },
    {
      "id": 2,
      "type": "cat",
      "price": 124.99
    },
    {
      "id": 3,
      "type": "fish",
      "price": 0.99
    }
  ]
  ```

  この出力を [API Gateway での REST API のテンプレート変換のマッピング](models-mappings.md) のマッピングテンプレートに従って変換します。

**`GET` 統合レスポンスを変換するには**
+ 次のコマンドを使用して、`GET` メソッドの統合レスポンスを更新します。*rest-api-id* と *resource-id* を実際の値に置き換えます。

  次のコマンドを使用して統合レスポンスを作成します。

  ```
  aws apigateway put-integration-response --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
    --status-code 200 \
    --selection-pattern "" \
    --response-templates '{"application/json": "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"}'
  ```

**`GET` メソッドをテストするには**
+ 次のコマンドを使用して `GET` メソッドをテストします。

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
  ```

  テストの出力に、変換されたレスポンスが表示されます。

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

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

1. 次のコマンドを使用して、`/pets` リソースで新しいメソッドを作成します。

   ```
   aws apigateway put-method --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --authorization-type "NONE" \
   ```

   このメソッドを使用すると、CloudFormation スタックで作成した DynamoDB テーブルにペット情報を送信できます。

1.  次のコマンドを使用して、`POST` メソッドで AWS のサービス統合を作成します。

   ```
   aws apigateway put-integration --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --type AWS \
     --integration-http-method POST \
     --uri "arn:aws:apigateway:us-east-2:dynamodb:action/PutItem" \
     --credentials arn:aws:iam::111122223333:role/data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG \
     --request-templates '{"application/json":"{\"TableName\":\"data-transformation-tutorial-cli-ddb\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"}'
   ```

1.  次のコマンドを使用して、`POST` メソッドの呼び出しが成功した場合のメソッドレスポンスを作成します。

   ```
   aws apigateway put-method-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200
   ```

1. 次のコマンドを使用して、`POST` メソッドの呼び出しが成功した場合の統合レスポンスを作成します。

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200 \
     --selection-pattern "" \
     --response-templates '{"application/json": "{\"message\": \"Your response was recorded at $context.requestTime\"}"}'
   ```

**`POST` メソッドをテストするには**
+ 次のコマンドを使用して、`POST` メソッドをテストします。

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method POST \
    --body '{\"id\": \"4\", \"type\": \"dog\", \"price\": \"321\"}'
  ```

  出力に、成功のメッセージが表示されます。

**CloudFormation スタックを削除するには**
+ 次のコマンドを使用して CloudFormation リソースを削除します。

  ```
  aws cloudformation delete-stack  --stack-name data-transformation-tutorial-cli
  ```

## 完成したデータ変換の CloudFormation テンプレート
<a name="api-gateway-data-transformations-full-cfn-stack"></a>

次の例は、完成した CloudFormation テンプレートです。これにより、API と、`GET` メソッドと `POST` メソッドを持つ `/pets` リソースを作成します。
+ `GET` メソッドは、`http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP エンドポイントからデータを取得します。出力データは、[API Gateway での REST API のテンプレート変換のマッピング](models-mappings.md) のマッピングテンプレートに従って変換されます。
+ `POST` メソッドを使用すると、ユーザーはマッピングテンプレートを使用して DynamoDB テーブルにペット情報を `POST` できます。

### CloudFormation テンプレートの例
<a name="mapping-template-cfn-example"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A completed Amazon API Gateway REST API that uses non-proxy integration to POST to an Amazon DynamoDB table and non-proxy integration to GET transformed pets data.
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  DynamoDBTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !Sub data-transformation-tutorial-complete
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: N
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  APIGatewayRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: APIGatewayDynamoDBPolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:PutItem'
                Resource: !GetAtt DynamoDBTable.Arn
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: data-transformation-complete-api
      ApiKeySourceType: HEADER
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: HTTP
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
        PassthroughBehavior: WHEN_NO_TEMPLATES
        IntegrationResponses:
          - StatusCode: '200'
            ResponseTemplates:
              application/json: "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"
      MethodResponses:
        - StatusCode: '200'
  PetsMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: POST
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: POST
        Uri: arn:aws:apigateway:us-west-1:dynamodb:action/PutItem
        PassthroughBehavior: NEVER
        RequestTemplates: 
          application/json: "{\"TableName\":\"data-transformation-tutorial-complete\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: "{\"message\": \"Your response was recorded at $context.requestTime\"}"
      MethodResponses:
        - StatusCode: '200'

  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiId:
    Description: API ID for CLI commands
    Value: !Ref Api
  ResourceId:
    Description: /pets resource ID for CLI commands
    Value: !Ref PetsResource
  ApiRole:
    Description: Role ID to allow API Gateway to put and scan items in DynamoDB table
    Value: !Ref APIGatewayRole
  DDBTableName:
    Description: DynamoDB table name
    Value: !Ref DynamoDBTable
```