

# API Gateway 中 REST API 的映射模板转换
<a name="models-mappings"></a>

映射模板转换使用映射模板来修改集成请求或集成响应。**映射模板是以 [Velocity Template Language（VTL）](https://velocity.apache.org/engine/devel/vtl-reference.html)表示的脚本，并使用 [JSONPath](https://goessner.net/articles/JsonPath/) 基于 `Content-type` 标头应用于有效载荷。使用映射模板转换时使用映射模板。此部分介绍与映射模板相关的概念性信息。

下图显示了与 PetStore 集成端点集成的 `POST /pets` 资源的请求生命周期。在此 API 中，用户发送有关宠物的数据，而集成端点返回与宠物关联的收养费。在此请求生命周期中，映射模板转换会将请求正文筛选到集成端点，并从集成端点筛选响应正文。

![\[请求生命周期示例\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/mapping-template-transforms.png)


以下各节解释请求和响应生命周期。

## 方法请求和集成请求
<a name="models-mappings-request"></a>

在前面的示例中，如果这是发送到方法请求的请求正文：

```
POST /pets
    HTTP/1.1
    Host:abcd1234.us-west-2.amazonaws.com
    Content-type: application/json
    
  {
    "id": 1,
    "type": "dog",
    "Age": 11,
  }
```

此请求正文的格式不适合集成端点使用，因此 API Gateway 执行映射模板转换。API Gateway 仅执行映射模板转换，因为已为 Content-Type `application/json` 定义了映射模板。如果您没有为 Content-Type 定义映射模板，则默认情况下，API Gateway 会通过集成请求将正文传递到集成端点。要修改此行为，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

以下映射模板先转换集成请求中的方法请求数据，然后将数据发送到集成端点：

```
#set($inputRoot = $input.path('$'))
  {
    "dogId" : "dog_"$elem.id,
    "Age": $inputRoot.Age
  }
```

1. `$inputRoot` 变量表示上一部分的原始 JSON 数据中的根对象。指令以 `#` 符号开头。

1. `dog` 是用户的 `id` 和字符串值的串联。

1. `Age` 来自方法请求正文。

然后，将以下输出转发到集成端点：

```
{
    "dogId" : "dog_1",
    "Age": 11
  }
```

## 集成响应和方法响应
<a name="models-mappings-response"></a>

成功请求集成端点后，端点会向 API Gateway 的集成响应发送响应。以下是来自集成端点的示例输出数据：

```
{
    "dogId" : "dog_1",
    "adoptionFee": 19.95,
}
```

方法响应预期的有效载荷与集成响应返回的有效载荷不同。API Gateway 执行映射模板转换。API Gateway 仅执行映射模板转换，因为已为 Content-Type `application/json` 定义了映射模板。如果您没有为 Content-Type 定义映射模板，则默认情况下，API Gateway 会通过对方法响应的集成响应传递正文。要修改此行为，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

```
#set($inputRoot = $input.path('$'))
  {
    "adoptionFee" : $inputRoot.adoptionFee,
  }
```

以下输出发送到方法响应：

```
{"adoptionFee": 19.95}
```

这就完成了示例映射模板转换。我们建议尽可能使用代理集成来转换数据，而不是使用映射模板转换。有关更多信息，请参阅 [选择 API Gateway API 集成类型](api-gateway-api-integration-types.md)。

# API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为
<a name="integration-passthrough-behaviors"></a>

如果方法请求有一个有效载荷，而您没有为 `Content-Type` 标头定义映射模板，则可以选择通过集成请求将客户端提供的请求有效载荷传递到后端，而不进行转换。此过程称为集成传递。

 传入请求的实际传递行为由此设置决定。这里有三个选项：

**当没有模板与请求的 Content-Type 标头匹配时**  
如果您希望在方法请求内容类型不匹配任何与映射模板关联的内容类型时，将方法请求正文通过集成请求发送到后端而不进行转换，则选择此选项。  
调用 API Gateway API 时，您通过将 `WHEN_NO_MATCH` 设置为[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)的 `passthroughBehavior` 属性值来选择此选项。

**未定义任何模板时（推荐）**  
如果您希望在集成请求中未定义映射模板时，将方法请求正文通过集成请求发送到后端而不进行转换，则选择此选项。如果在选择此选项时定义了模板，则具有与任何定义的映射模板都不匹配的有效载荷和内容类型的方法请求将遭到拒绝，并返回“HTTP 415 媒体类型不受支持”响应。  
调用 API Gateway API 时，您通过将 `WHEN_NO_TEMPLATES` 设置为[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)的 `passthroughBehavior` 属性值来选择此选项。

**从不**  
如果您不希望在集成请求中未定义映射模板时，将方法请求正文通过集成请求发送到后端而不进行转换，则选择此选项。如果选择此选项时定义了模板，则会以“HTTP 415 Unsupported Media Type”响应拒绝未映射内容类型的方法请求。  
调用 API Gateway API 时，您通过将 `NEVER` 设置为[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)的 `passthroughBehavior` 属性值来选择此选项。

 以下示例显示了可能的传递行为。

示例 1：`application/json` 内容类型的集成请求中定义了一个映射模板。


| Content-type | 传递选项 | 行为 | 
| --- | --- | --- | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1MATCH | 使用模板转换请求负载。 | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1TEMPLATES | 使用模板转换请求负载。 | 
| 无 API Gateway 默认为 `application/json` | NEVER | 使用模板转换请求负载。 | 
| application/json | WHEN\$1NO\$1MATCH | 使用模板转换请求负载。 | 
| application/json | WHEN\$1NO\$1TEMPLATES | 使用模板转换请求负载。 | 
| application/json | NEVER | 使用模板转换请求负载。 | 
| application/xml | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/xml | WHEN\$1NO\$1TEMPLATES | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/xml | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 

示例 2：`application/xml` 内容类型的集成请求中定义了一个映射模板。


| Content-type | 传递选项 | 行为 | 
| --- | --- | --- | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1TEMPLATES | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| 无 API Gateway 默认为 `application/json` | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/json | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/json | WHEN\$1NO\$1TEMPLATES | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/json | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/xml | WHEN\$1NO\$1MATCH | 使用模板转换请求负载。 | 
| application/xml | WHEN\$1NO\$1TEMPLATES | 使用模板转换请求负载。 | 
| application/xml | NEVER | 使用模板转换请求负载。 | 

示例 3：集成请求中未定义映射模板。


| Content-type | 传递选项 | 行为 | 
| --- | --- | --- | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1TEMPLATES | 请求负载未转换，并按原样发送到后端。 | 
| 无 API Gateway 默认为 `application/json` | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/json | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/json | WHEN\$1NO\$1TEMPLATES | 请求负载未转换，并按原样发送到后端。 | 
| application/json | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/xml | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/xml | WHEN\$1NO\$1TEMPLATES | 请求负载未转换，并按原样发送到后端。 | 
| application/xml | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 

# API Gateway 中 REST API 的附加映射模板示例
<a name="example-photos"></a>

以下示例显示了 API Gateway 中的相册 API，该 API 使用映射模板转换集成请求和集成响应数据。它还使用数据模型来定义方法请求和集成响应有效载荷。有关数据模型的更多信息，请参阅[针对 REST API 的数据模型](models-mappings-models.md)。

## 方法请求和集成请求
<a name="example-photos-request"></a>

以下是定义方法请求正文的模型。此输入模型要求调用方上传一张照片页面，每页至少需要 10 张照片。您可以使用此输入模型生成 SDK 或为您的 API 使用请求验证。在使用请求验证时，如果方法请求正文不符合模型的数据结构，则 API Gateway 会使请求失败。

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosInputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "object",
      "required" : [
      "photo"
      ],
      "properties": {
        "page": { "type": "integer" },
        "pages": { "type": "string" },
        "perpage": { "type": "integer", "minimum" : 10 },
        "total": { "type": "string" },
        "photo": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "owner": { "type": "string" },
              "photographer_first_name" : {"type" : "string"},
              "photographer_last_name" : {"type" : "string"},
              "secret": { "type": "string" },
              "server": { "type": "string" },
              "farm": { "type": "integer" },
              "title": { "type": "string" },
              "ispublic": { "type": "boolean" },
              "isfriend": { "type": "boolean" },
              "isfamily": { "type": "boolean" }
            }
          }
        }
      }
    }
  }
}
```

以下是遵循先前数据模型的数据结构的方法请求正文示例。

```
{
  "photos": {
    "page": 1,
    "pages": "1234",
    "perpage": 100,
    "total": "123398",
    "photo": [
      {
        "id": "12345678901",
        "owner": "23456789@A12",
        "photographer_first_name" : "Saanvi",
        "photographer_last_name" : "Sarkar",
        "secret": "abc123d456",
        "server": "1234",
        "farm": 1,
        "title": "Sample photo 1",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      },
      {
        "id": "23456789012",
        "owner": "34567890@B23",
        "photographer_first_name" : "Richard",
        "photographer_last_name" : "Roe",
        "secret": "bcd234e567",
        "server": "2345",
        "farm": 2,
        "title": "Sample photo 2",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      }
    ]
  }
}
```

在此示例中，如果之前的方法请求正文是由客户端提交的，则此映射模板会转换有效载荷，以匹配集成端点所需的格式。

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.ispublic,
      "isfriend": $elem.isfriend,
      "isfamily": $elem.isfamily
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

以下示例是来自转换的输出数据：

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

这些数据发送到集成请求，然后发送到集成端点。

## 集成响应和方法响应
<a name="photos-example-response"></a>

以下是来自集成端点的照片数据的输出模型示例。您可以将此模型用于方法响应模型，这在为 API 生成强类型 SDK 时是必需的。这会导致输出将在 Java 或 Objective-C 中强制转换为适当的类。

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosOutputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "photographedBy": { "type": "string" },
          "title": { "type": "string" },
          "ispublic": { "type": "boolean" },
          "isfriend": { "type": "boolean" },
          "isfamily": { "type": "boolean" }
        }
      }
    }
  }
}
```

集成端点可能不会以符合此模型的数据结构的响应进行响应。例如，集成响应可能如下所示：

```
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    }		
  ]
}
```

以下示例映射模板将集成响应数据转换为方法响应所期望的格式：

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.public,
      "isfriend": $elem.friend,
      "isfamily": $elem.family
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

以下示例是来自转换的输出数据：

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

这些数据发送到方法响应，然后再发送回客户端。

# 针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码
<a name="apigateway-override-request-response-parameters"></a>

您可以使用映射模板转换来覆盖任何类型的请求参数、响应标头或响应状态代码。可以使用映射模板来执行以下操作：
+ 执行多对一参数映射
+ 在应用标准 API Gateway 映射后覆盖参数
+ 根据正文内容或其他参数值有条件地映射参数
+ 以编程方式创建新参数
+ 覆盖由集成端点返回的状态代码

覆盖是最终的。对于每个参数，覆盖只能应用一次。如果您多次尝试覆盖同一个参数，则 API Gateway 会返回 `5XX` 响应。如果您必须在整个模板中多次覆盖相同的参数，我们建议创建一个变量并在模板末尾应用覆盖。仅在解析整个模板后应用模板。

## 示例 1：基于集成正文覆盖状态代码
<a name="apigateway-override-request-response-examples"></a>

以下示例使用[示例 API](api-gateway-create-api-from-example.md) 基于集成响应正文覆盖状态代码。

------
#### [ AWS 管理控制台 ]

**基于集成响应正文覆盖状态代码**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择**创建 API**。

1. 对于 **REST API**，选择**构建**。

1. 对于 **API 详细信息**，选择**示例 API**。

1. 选择**创建 API**。

   API Gateway 创建一个示例宠物商店 API。要检索有关宠物的信息，您使用 API 方法请求 `GET /pets/{petId}`，其中 `{petId}` 是与宠物的 ID 号相对应的路径参数。

   在此示例中，当检测到错误条件时，您将 `GET` 方法的响应代码覆盖为 `400`。

1. 在**资源**树中，选择 `/{petId}` 下的 `GET` 方法。

1. 首先，测试 API 的当前实现。

   选择**测试**选项卡。您可能需要选择右箭头按钮，以显示该选项卡。

1. 对于 **petId**，输入 **-1**，然后选择**测试**。

   **响应正文**指示超出范围错误：

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   此外，**日志**下的最后一行的结尾为：`Method completed with status: 200`。

   集成已成功完成，但出现错误。现在，您将根据集成响应覆盖状态代码。

1. 在**集成响应**选项卡上，对于**默认 - 响应**，选择**编辑**。

1. 选择**映射模板**。

1. 选择**添加映射模板**。

1. 对于**内容类型**，输入 **application/json**。

1. 对于**模板正文**，输入以下内容：

   ```
   #set($inputRoot = $input.path('$'))
   $input.json("$")
   #if($inputRoot.toString().contains("error"))
   #set($context.responseOverride.status = 400)
   #end
   ```

   如果集成响应包含字符串 `error`，则此映射模板使用 `$context.responseOverride.status` 变量将状态代码覆盖为 `400`。

1. 选择**保存**。

1. 选择**测试**选项卡。

1. 对于 **petId**，输入 **-1**。

1. 在结果中，**响应正文**表示超出范围错误：

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   不过，**日志**下的最后一行现在的结尾为：`Method completed with status: 400`。

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 1
          description: Example pet store API.
          version: "2025-01-14T00:13:18Z"
        paths:
          /pets/{petId}:
            get:
              parameters:
                - name: petId
                  in: path
                  required: true
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}
                responses:
                  default:
                    statusCode: "200"
                    responseTemplates:
                      application/json: |-
                        #set($inputRoot = $input.path('$'))
                        $input.json("$")
                        #if($inputRoot.toString().contains("error"))
                        #set($context.responseOverride.status = 400)
                        #end
                requestParameters:
                  integration.request.path.petId: method.request.path.petId
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

以下 OpenAPI 定义创建 `GET pets/{petId}` 资源并根据集成主体覆盖状态代码。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 1",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:13:18Z"
  },
  "paths" : {
    "/pets/{petId}" : {
      "get" : {
        "parameters" : [ {
          "name" : "petId",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n$input.json(\"$\")\n#if($inputRoot.toString().contains(\"error\"))\n#set($context.responseOverride.status = 400)\n#end"
              }
            }
          },
          "requestParameters" : {
            "integration.request.path.petId" : "method.request.path.petId"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Pet" : {
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string"
          },
          "price" : {
            "type" : "number"
          }
        }
      }
    }
  }
}
```

------

## 示例 2：覆盖请求标头并创建新标头
<a name="apigateway-override-request-response-examples-2"></a>

以下示例使用[示例 API](api-gateway-create-api-from-example.md) 来覆盖请求标头并创建新的标头。

------
#### [ AWS 管理控制台 ]

**通过创建新标头覆盖方法的请求标头**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择您在先前教程中创建的示例 API。API 的名称应为 **PetStore**。

1. 在**资源**树中，选择 `/pet` 下的 `GET` 方法。

1. 在**方法请求**选项卡上，对于**方法请求设置**，选择**编辑**。

1. 选择 **HTTP 请求标头**，然后选择**添加标头**。

1. 对于**名称**，请输入 **header1**。

1. 选择**添加标头**，然后创建第二个标头，名为 **header2**。

1. 选择**保存**。

   现在，您可以使用映射模板将这些标头合并为一个标头值。

1. 在**集成请求**选项卡上，对于**集成请求设置**，选择**编辑**。

1. 对于**请求正文传递**，选择**当未定义模板时（推荐）**。

1. 选择**映射模板**，然后执行以下操作：

   1. 选择**添加映射模板**。

   1. 对于**内容类型**，输入 **application/json**。

   1. 对于**模板正文**，输入以下内容：

      ```
      #set($header1Override = "pets")
      #set($header3Value = "$input.params('header1')$input.params('header2')")
      $input.json("$")
      #set($context.requestOverride.header.header3 = $header3Value)
      #set($context.requestOverride.header.header1 = $header1Override)
      #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
      ```

      此映射模板使用字符串 `pets` 覆盖 `header1`，并创建一个名为 `$header3Value` 的多值标头，该标头将 `header1` 和 `header2` 组合在一起。

1. 选择**保存**。

1. 选择**测试**选项卡。

1. 在**标头**下，复制以下代码：

   ```
   header1:header1Val
   header2:header2Val
   ```

1. 选择 **Test (测试)**。

   在**日志**中，您应看到一个包含此文本的条目：

   ```
   Endpoint request headers: {header3=header1Valheader2Val, 
   header2=header2Val, header1=pets, x-amzn-apigateway-api-id=api-id,
   Accept=application/json, multivalueheader=pets,header1Valheader2Val}
   ```

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 2
          description: Example pet store API.
          version: "2025-01-14T00:36:18Z"
        paths:
          /pets:
            get:
              parameters:
                - name: header2
                  in: header
                  schema:
                    type: string
                - name: page
                  in: query
                  schema:
                    type: string
                - name: type
                  in: query
                  schema:
                    type: string
                - name: header1
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.header1: method.request.header.header1
                  integration.request.header.header2: method.request.header.header2
                  integration.request.querystring.page: method.request.querystring.page
                  integration.request.querystring.type: method.request.querystring.type
                requestTemplates:
                  application/json: |-
                    #set($header1Override = "pets")
                    #set($header3Value = "$input.params('header1')$input.params('header2')")
                    $input.json("$")
                    #set($context.requestOverride.header.header3 = $header3Value)
                    #set($context.requestOverride.header.header1 = $header1Override)
                    #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

 以下 OpenAPI 定义创建 `GET pets` 资源，并覆盖请求标头和创建新的标头。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 2",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:36:18Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "header2",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "page",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "type",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "header1",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.header1" : "method.request.header.header1",
            "integration.request.header.header2" : "method.request.header.header2",
            "integration.request.querystring.page" : "method.request.querystring.page",
            "integration.request.querystring.type" : "method.request.querystring.type"
          },
          "requestTemplates" : {
            "application/json" : "#set($header1Override = \"pets\")\n#set($header3Value = \"$input.params('header1')$input.params('header2')\")\n$input.json(\"$\")\n#set($context.requestOverride.header.header3 = $header3Value)\n#set($context.requestOverride.header.header1 = $header1Override)\n#set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

要使用映射模板覆盖，请添加以下一个或多个 `$context` 变量。有关 `$context` 变量的列表，请参阅[数据转换的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)。

# 教程：修改集成请求和响应以集成到 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
```

# 使用变量来映射 API Gateway 的模板转换的示例
<a name="api-gateway-mapping-variable-examples"></a>

以下示例显示了如何在映射模板中使用 `$context`、`input` 和 `util` 变量。您可以使用模拟集成或用于将输入事件返回到 API Gateway 的 Lambda 非代理集成。有关数据转换的所有支持的变量的列表，请参阅 [API Gateway 的用于数据转换的变量](api-gateway-mapping-template-reference.md)。

## 示例 1：将多个 `$context` 变量传递到集成端点
<a name="context-variables-template-example"></a>

以下示例显示了一个映射模板，该模板将传入的 `$context` 变量映射到后端变量，这些变量在集成请求负载中的名称稍有不同：

```
{
    "stage" : "$context.stage",
    "request_id" : "$context.requestId",
    "api_id" : "$context.apiId",
    "resource_path" : "$context.resourcePath",
    "resource_id" : "$context.resourceId",
    "http_method" : "$context.httpMethod",
    "source_ip" : "$context.identity.sourceIp",
    "user-agent" : "$context.identity.userAgent",
    "account_id" : "$context.identity.accountId",
    "api_key" : "$context.identity.apiKey",
    "caller" : "$context.identity.caller",
    "user" : "$context.identity.user",
    "user_arn" : "$context.identity.userArn"
}
```

此映射模板的输出应与以下内容类似：

```
{
  stage: 'prod',
  request_id: 'abcdefg-000-000-0000-abcdefg',
  api_id: 'abcd1234',
  resource_path: '/',
  resource_id: 'efg567',
  http_method: 'GET',
  source_ip: '192.0.2.1',
  user-agent: 'curl/7.84.0',
  account_id: '111122223333',
  api_key: 'MyTestKey',
  caller: 'ABCD-0000-12345',
  user: 'ABCD-0000-12345',
  user_arn: 'arn:aws:sts::111122223333:assumed-role/Admin/carlos-salazar'
}
```

其中一个变量是 API 密钥。此示例假设方法需要 API 密钥。

## 示例 2：通过 JSON 有效载荷将所有请求参数传递给集成端点
<a name="input-examples-mapping-templates"></a>

以下示例通过 JSON 有效载荷将所有请求参数（包括 `path`、`querystring` 和 `header` 参数）传递到集成端点：

```
#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}
```

如果请求具有以下输入参数：
+ 名为 `myparam` 的路径参数
+ 查询字符串参数 `querystring1=value1,value2`
+ 标头 `"header1" : "value1"`。

此映射模板的输出应与以下内容类似：

```
{"params":{"path":{"example2":"myparamm"},"querystring":{"querystring1":"value1,value2"},"header":{"header1":"value1"}}}
```

## 示例 3：将方法请求的一部分传递给集成端点
<a name="input-example-json-mapping-template"></a>

 以下示例使用输入参数 `name` 仅检索 `name` 参数，并使用输入参数 `input.json('$')` 检索方法请求的整个正文：

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$') 
}
```

对于包含查询字符串参数 `name=Bella&type=dog` 和以下正文的请求：

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body" : {"Price":"249.99","Age":"6"}
}
```

此映射模板移除了查询字符串参数 `type=dog`。

 如果 JSON 输入包含无法通过 JavaScript 解析的非转义字符，则 API Gateway 可能会返回 400 响应。应用 `$util.escapeJavaScript($input.json('$'))` 来确保正确解析 JSON 输入。

上面的示例在应用了 `$util.escapeJavaScript($input.json('$'))` 之后会如下所示：

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$'))"
}
```

在这种情况下，此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body": {"Price":"249.99","Age":"6"}
}
```

## 示例 4：使用 JSONPath 表达式将方法请求的一部分传递给集成端点
<a name="input-example-inputs-mapping-template"></a>

以下示例使用 JSONPath 表达式从请求正文中仅检索输入参数 `name` 和 `Age`：

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$.Age')  
}
```

对于包含查询字符串参数 `name=Bella&type=dog` 和以下正文的请求：

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body" : "6"
}
```

此映射模板从正文中移除查询字符串参数 `type=dog` 和 `Price` 字段。

 如果方法请求负载包含无法通过 JavaScript 解析的非转义字符，则 API Gateway 可能会返回 `400` 响应。应用 `$util.escapeJavaScript()` 来确保正确解析 JSON 输入。

上面的示例在应用了 `$util.escapeJavaScript($input.json('$.Age'))` 之后会如下所示：

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$.Age'))" 
}
```

在这种情况下，此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body": "\"6\""
}
```

## 示例 5：使用 JSONPath 表达式将有关方法请求的信息传递到集成端点
<a name="input-example-request-and-response"></a>

以下示例使用 `$input.params()`、`$input.path()` 和 `$input.json()` 向集成端点发送有关方法请求的信息。此映射模板使用 `size()` 方法来提供列表中元素的数量。

```
{
    "id" : "$input.params('id')",
    "count" : "$input.path('$.things').size()",
    "things" : $input.json('$.things')
}
```

对于包含路径参数 `123` 和以下正文的请求：

```
{
      "things": {
            "1": {},
            "2": {},
            "3": {}
      }
}
```

此映射模板的输出应与以下内容类似：

```
{"id":"123","count":"3","things":{"1":{},"2":{},"3":{}}}
```

 如果方法请求负载包含无法通过 JavaScript 解析的非转义字符，则 API Gateway 可能会返回 `400` 响应。应用 `$util.escapeJavaScript()` 来确保正确解析 JSON 输入。

上面的示例在应用了 `$util.escapeJavaScript($input.json('$.things'))` 之后会如下所示：

```
{
     "id" : "$input.params('id')",
     "count" : "$input.path('$.things').size()",
     "things" : "$util.escapeJavaScript($input.json('$.things'))"
}
```

此映射模板的输出应与以下内容类似：

```
{"id":"123","count":"3","things":"{\"1\":{},\"2\":{},\"3\":{}}"}
```