

# 教程：修改集成请求和响应以集成到 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 拥有的 `/pets` 资源具有 `GET` 和 `POST` 方法。
+ `GET` 方法将从 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点获取数据。输出数据将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板进行转换。
+ `POST` 方法将允许用户使用映射模板将宠物信息 `POST` 到 Amazon DynamoDB 表中。

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/data-transformation-tutorial-console.zip)。您将使用此模板创建 DynamoDB 表来发布宠物信息和不完整的 API。您将在 API Gateway 控制台中完成其余步骤。

**创建 CloudFormation 堆栈**

1. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择**创建堆栈**，然后选择**使用新资源(标准)**。

1. 对于**指定模板**，选择**上传模板文件**。

1. 选择您下载的模板。

1. 选择**下一步**。

1. 对于**堆栈名称**，输入 **data-transformation-tutorial-console**，然后选择**下一步**。

1. 对于**配置堆栈选项**，请选择**下一步**。

1. 对于**功能**，请确认 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`。这意味着 API 将拒绝所有不是 application/json 的内容类型。有关集成传递行为的更多信息，请参阅[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. 对于 **Content-Type**，输入 **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. 选择**测试**。

   输出应显示您的成功消息。

    您可以通过 [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/) 打开 DynamoDB 控制台，以验证示例项目是否在您的表中。

**删除 CloudFormation 堆栈**

1. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择您的 CloudFormation 堆栈。

1. 选择**删除**，然后确认您的选择。

## 使用 AWS CLI 设置数据转换
<a name="mapping-example-cli"></a>

在本教程中，您将使用以下 .zip 文件 [data-transformation-tutorial-cli.zip](samples/data-transformation-tutorial-cli.zip) 创建不完整的 API 和 DynamoDB 表。这个不完整的 API 所具有的 `/pets` 资源包含与 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点集成的 `GET` 方法。您将创建 `POST` 方法以连接到 DynamoDB 表，并使用映射模板将数据输入到 DynamoDB 表中。
+ 您将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板转换输出数据。
+ 您将创建 `POST` 方法，以允许用户使用映射模板将宠物信息 `POST` 到 Amazon DynamoDB 表中。

**创建 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`）。[安装 Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install)，获取 Ubuntu 和 Bash 与 Windows 集成的版本。本指南中的示例 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 和一个 DynamoDB 表，该表的 `/pets` 资源具有 `GET` 和 `POST` 方法。
+ `GET` 方法将从 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点获取数据。输出数据将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板进行转换。
+ `POST` 方法将允许用户使用映射模板将宠物信息 `POST` 到 DynamoDB 表中。

### 示例 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
```