

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# API Gateway 中 REST API 的映射範本轉換
<a name="models-mappings"></a>

映射範本轉換會使用映射範本來修改您的整合請求或整合回應。*映射範本*是以 [Velocity 範本語言 (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_tw/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 時，您可以透過在[整合](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)上將 `WHEN_NO_MATCH` 設定為 `passthroughBehavior` 屬性值來選擇此選項。

**未定義範本時 (建議)**  
當整合請求中未定義任何對應範本時，如果您想要讓方法請求內文透過整合請求傳遞到後端而不進行轉換，請選擇此選項。如果選取此選項時已定義範本，則具有承載但內容類型不符合任何已定義映射範本的方法請求將會遭拒，並顯示 HTTP 415 Unsupported Media Type (不支援的媒體類型) 回應。  
呼叫 API Gateway API 時，您可以透過在[整合](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)上將 `WHEN_NO_TEMPLATES` 設定為 `passthroughBehavior` 屬性值來選擇此選項。

**從不**  
當整合請求中未定義任何對應範本時，如果您不想要讓方法請求內文透過整合請求傳遞到後端而不進行轉換，請選擇此選項。如果選取此選項時已定義範本，未映射內容類型的方法請求會遭到拒絕，並顯示 HTTP 415 Unsupported Media Type (不支援的媒體類型) 回應。  
呼叫 API Gateway API 時，您可以透過在[整合](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)上將 `NEVER` 設定為 `passthroughBehavior` 屬性值來選擇此選項。

 下列範例說明可能的傳遞行為。

範例 1：針對 `application/json` 內容類型在整合請求中定義的一個對應範本。


| Content-type | 傳遞選項 | Behavior (行為) | 
| --- | --- | --- | 
| 無 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 | 傳遞選項 | Behavior (行為) | 
| --- | --- | --- | 
| 無 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 | 傳遞選項 | Behavior (行為) | 
| --- | --- | --- | 
| 無 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. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇 **Create API (建立 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. 在結果中，**Response Body (回應內文)** 表示超出範圍錯誤：

   ```
   {
     "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. 在以下網址登入 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])
      ```

      此映射範本會將 `header1` 覆寫為字串 `pets`，並建立結合 `header1` 和 `header2` 且名為 `$header3Value` 的多值標頭。

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>

下列教學課程說明如何使用映射範本轉換來設定映射範本，以使用主控台和 CLI AWS 轉換整合請求和回應。

**Topics**
+ [

## 使用 API Gateway 主控台設定資料轉換
](#mapping-example-console)
+ [

## 使用 CLI AWS 設定資料轉換
](#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. 在 https：//[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 開啟 CloudFormation 主控台。

1. 選擇 **Create stack (建立堆疊)**，然後選擇 **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. 針對 **功能**，確認 CloudFormation 可以在您的帳戶中建立 IAM 資源。

1. 選擇**下一步**，然後選擇**提交**。

CloudFormation 會佈建範本中指定的資源。完成資源佈建可能需要幾分鐘的時間。當您的 CloudFormation 堆疊狀態為 **CREATE\$1COMPLETE** 時，您就可以繼續進行下一個步驟。

**測試 `GET` 整合回應**

1. 在 CloudFormation 堆疊**的資源**索引標籤上**data-transformation-tutorial-console**，選取 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 created this role，以允許 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. 針對 **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. 在 https：//[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 開啟 CloudFormation 主控台。

1. 選取您的 CloudFormation 堆疊。

1. 選擇**刪除**，然後確認您的選擇。

## 使用 CLI AWS 設定資料轉換
<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`)。若要取得 Ubuntu 和 Bash 的 Windows 整合版本，請[安裝適用於 Linux 的 Windows 子系統](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 範本，其會使用 和 `POST`方法建立具有 `/pets` 資源的 API `GET`和 DynamoDB 資料表。
+ `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` 變數。您可以使用模擬整合或 Lambda 非代理整合，將輸入事件傳回至 API Gateway。如需資料轉換支援的所有變數的清單，請參閱 [用於 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\":{}}"}
```