

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

# 在 API Gateway 中使用 REST API 的階段變數
<a name="stage-variables"></a>

階段變數是鍵值對，您可以定義為與 REST API 部署階段相關聯的組態屬性。它們的作用如同環境變數，可用於 API 設定和對應範本。您可以使用 API Gateway 中的部署階段，管理每個 API 的多個發行階段，並使用階段變數設定 API 部署階段與不同的後端端點互動。

階段變數並非用於敏感資料，例如登入資料。若要將敏感資料傳遞至整合，請使用 AWS Lambda 授權方。您可以將敏感資料傳遞至 Lambda 授權方輸出中的整合。如需進一步了解，請參閱[來自 API Gateway Lambda 授權方的輸出](api-gateway-lambda-authorizer-output.md)。

## 階段變數的使用案例
<a name="use-cases"></a>

下列為您的階段變數的使用案例。

**指定不同的後端端點**  
您的 API 可將 `GET` 請求當做 HTTP 代理傳到後端 Web 主機。您可以使用階段變數，如此一來，當讓 API 呼叫者調用您的生產端點時，API Gateway 就會呼叫 `example.com`。然後，當 API 呼叫者調用 Beta 階段時，API Gateway 會呼叫不同的 Web 主機，例如 `beta.example.com`。同樣地，階段變數可用來指定您 API 中每個階段的不同 AWS Lambda 函數名稱。您無法使用階段變數來設定不同的整合端點，例如將 `GET` 請求指向一個階段中的 HTTP 代理整合，以及在另一個階段中的 Lambda 代理整合。  
將 Lambda 函數名稱指定為階段變數值時，您必須在 Lambda 函數中手動設定許可。當您在 API Gateway 主控台中指定 Lambda 函數時，將彈出 AWS CLI 命令來設定適當的許可。您也可以使用下列 AWS CLI 命令來執行此操作。  

```
aws lambda add-permission --function-name "arn:aws:lambda:us-east-2:123456789012:function:my-function" --source-arn "arn:aws:execute-api:us-east-2:123456789012:api_id/*/HTTP_METHOD/resource" --principal apigateway.amazonaws.com --statement-id apigateway-access --action lambda:InvokeFunction
```

**使用映射範本傳遞資訊**  
您可以存取映射範本中的階段變數，或將組態參數傳送到 AWS Lambda 或 HTTP 後端。例如，您可能希望在您 API 的多個階段中重複使用相同的 Lambda 函數，但此函數應該從不同的 Amazon DynamoDB 資料表讀取資料，視階段而定。在產生 Lambda 函數請求的對應範本中，您可以使用階段變數將資料表名稱傳送給 Lambda。

若要使用階段變數，請先設定階段變數，然後為其指派值。例如，要自訂 HTTP 整合端點時，先建立 `url` 階段變數，然後在 API 的整合請求中輸入階段變數值 **http://\$1\$1stageVariables.url\$1**。此值會指示 API Gateway 在執行時間替換您的階段變數 `${}`，視您 API 執行的階段而定。如需詳細資訊，請參閱[在 API Gateway 設定 REST API 的階段變數](how-to-set-stage-variables-aws-console.md)。

# 在 API Gateway 設定 REST API 的階段變數
<a name="how-to-set-stage-variables-aws-console"></a>

這一節顯示如何使用 Amazon API Gateway 主控台，為範例 API 的兩個部署階段設定階段變數。若要了解如何在 API Gateway 中使用階段變數，建議您遵循本節中的所有程序。

## 先決條件
<a name="how-to-set-stage-variables-aws-console-prerequisites"></a>

開始之前，請務必先達成以下必要條件：
+ 您必須擁有 API Gateway 中可用的 API。請遵循中的說明進行[在 APIs Gateway 中開發 REST API](rest-api-develop.md)
+ 您必須至少已部署一次 API。請遵循中的說明進行[在 API Gateway 中部署 REST API](how-to-deploy-api.md)
+ 您必須為已部署的 API 建立第一個階段。請遵循中的說明進行[建立新的階段](set-up-stages.md#how-to-create-stage-console)

  

## 利用具階段變數的 API 調用 HTTP 端點
<a name="how-to-set-stage-variables-aws-console-http-endpoint"></a>

此程序說明如何為 HTTP 端點建立階段變數，並為 API 建立兩個階段。此外，您可以建立階段變數 `url`、`stageName` 和 `function`，並將其用於本節中的下列程序。

**利用具階段變數的 API 調用 HTTP 端點**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 建立 API，然後在 API 根資源上建立 `GET` 方法。將整合類型設定為 **HTTP**，並將**端點 URL** 設定為 **http://\$1\$1stageVariables.url\$1**。

1. 將 API 部署至名為 **beta** 的新階段。

1. 在主導覽窗格中，選擇**階段**，然後選取 **beta** 階段。

1. 在**階段變數**索引標籤上，選擇**編輯**。

1. 選擇**新增階段變數**。

1. 對於**名稱**，輸入 **url**。針對**值**，輸入 **httpbin.org/get**。

1. 選擇**新增階段變數**，然後執行下列動作：

   對於**名稱**，輸入 **stageName**。針對**值**，輸入 **beta**。

1. 選擇**新增階段變數**，然後執行下列動作：

   對於**名稱**，輸入 **function**。針對**值**，輸入 **HelloWorld**。

1. 選擇**儲存**。

1.  現在建立第二個階段。從**階段**導覽窗格選擇**建立**。針對**階段名稱**，輸入 **prod**。從**部署**選取最近的部署，然後選擇**建立階段**。

1.  如同在 **beta** 階段，請將相同的三個階段變數 (**url**、**stageName** 和 **function**) 分別設為不同的值 (**petstore-demo-endpoint.execute-api.com/petstore/pets**、**prod** 和 **HelloEveryone**)。

1. 在 **Stages (階段)** 導覽窗格中，選擇 **beta**。在**階段詳細資訊**下，選擇複製圖示以複製您的 API 的調用 URL，然後在 Web 瀏覽器中輸入您的 API 調用 URL。這會啟動 **beta** 階段在 API 根資源上的 `GET` 請求。
**注意**  
**Invoke URL** (呼叫 URL) 連結在其 **beta** 階段會指向 API 的根資源。在 Web 瀏覽器中輸入 URL 會對根資源呼叫 **beta** 階段 `GET` 方法。如果方法是在子資源中定義，不是在根資源本身中定義，則在 Web 瀏覽器中輸入 URL 會傳回 `{"message":"Missing Authentication Token"}` 錯誤回應。在這種情況下，您必須將特定子資源的名稱附加至 **Invoke URL (呼叫 URL)** 連結。

1. 您從 **beta** 階段 `GET` 請求取得的回應，如旁所示。您也可以使用瀏覽器導覽至 **http://httpbin.org/get** 驗證結果。此值已在 **beta** 階段指派給 `url` 變數。兩個回應完全相同。

1. 在 **Stages (階段)** 導覽窗格中，選擇 **prod** 階段。在**階段詳細資訊**下，選擇複製圖示以複製您的 API 的調用 URL，然後在 Web 瀏覽器中輸入您的 API 調用 URL。這會啟動 **prod** 階段在 API 根資源上的 `GET` 請求。

1. 您從 **prod** 階段 `GET` 請求取得的回應，如旁所示。您可以使用瀏覽器導覽至 **http://petstore-demo-endpoint.execute-api.com/petstore/pets**，以驗證結果。此值已在 **prod** 階段指派給 `url` 變數。兩個回應完全相同。

## 將階段特定的中繼資料傳遞至 HTTP 後端
<a name="how-to-set-stage-variables-aws-console-stage-metadata"></a>

此程序說明如何使用查詢參數表達式中的階段變數值，將階段特定中繼資料傳送到 HTTP 後端。我們會使用在上一個程序中宣告的 `stageName` 階段變數。

**將階段特定的中繼資料傳遞至 HTTP 後端**

1. 在 **Resource (資源)** 導覽窗格中選擇 **GET** 方法。

   若要將查詢字串參數新增至方法的 URL，請選擇**方法請求**索引標籤，然後在**方法請求設定**區段中，選擇**編輯**。

1. 選擇 **URL 查詢字串參數**，然後執行下列動作：

   1. 選擇**新增查詢字串**。

   1. 對於**名稱**，輸入 **stageName**。

   1. 將**必要**和**快取**保持關閉。

1. 選擇**儲存**。

1. 選擇**整合請求**索引標籤，然後在**整合請求設定**區段中，選擇**編輯**。

1. 對於**端點 URL**，將 **?stageName=\$1\$1stageVariables.stageName\$1** 附加至先前定義的 URL 值，使整個**端點 URL** 成為 **http://\$1\$1stageVariables.url\$1?stageName=\$1\$1stageVariables.stageName\$1**。

1. 選擇**部署 API**，並選取 **beta** 階段。

1. 在主導覽窗格中，選擇**階段**。在 **Stages (階段)** 導覽窗格中，選擇 **beta**。在**階段詳細資訊**下，選擇複製圖示以複製您的 API 的調用 URL，然後在 Web 瀏覽器中輸入您的 API 調用 URL。
**注意**  
 我們在此使用 beta 階段，是因為 HTTP 端點如 `url` 變數 "http://httpbin.org/get" 所指定，接受查詢參數表達式，並傳回它們做為其回應的 `args` 物件。

1. 您會收到以下回應。請注意，指派給 `beta` 階段變數的 `stageName`，在後端傳送為 `stageName` 引數。

      
![\[使用 url 階段變數藉由 HTTP 端點對 API 的 GET 方法做出回應。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/stageVariables-new-console-invoke-beta-stage-with-url-and-stageName-response.png)

## 透過 API 使用階段變數調用 Lambda 函數
<a name="how-to-set-stage-variables-aws-console-lambda-function"></a>

此程序說明如何使用階段變數呼叫 Lambda 函數做為 API 的後端。您使用的是在 `function` 中宣告的 [利用具階段變數的 API 調用 HTTP 端點](#how-to-set-stage-variables-aws-console-http-endpoint) 階段變數。

 將 Lambda 函數設定為階段變數值時，請使用函數的本機名稱，這可能會包括其別名或版本規格，如 **HelloWorld**、**HelloWorld:1** 或 **HelloWorld:alpha**。請勿使用函數的 ARN (例如，**arn:aws:lambda:us-east-1:123456789012:function:HelloWorld**)。API Gateway 主控台假設 Lambda 函數的階段變數值為不完整的函數名稱，會將指定的階段變數擴充為 ARN。

**透過 API 使用階段變數調用 Lambda 函數**

1. 使用預設 Node.js 執行期建立名為 **HelloWorld** 的 Lambda 函數。程式碼必須包含下列內容：

   ```
   export const handler = function(event, context, callback) {
       if (event.stageName)
           callback(null, 'Hello, World! I\'m calling from the ' + event.stageName + ' stage.');
       else
           callback(null, 'Hello, World! I\'m not sure where I\'m calling from...');
   };
   ```

   如需如何建立 Lambda 函數的詳細資訊，請參閱 [REST API 主控台入門](getting-started-rest-new-console.md#getting-started-rest-new-console-create-function)。

1. 在**資源**窗格中，選取**建立資源**，然後執行下列動作：

   1. 針對**資源路徑**，選取 **/**。

   1. 針對**資源名稱**，輸入 **lambdav1**。

   1. 選擇**建立資源**。

1. 選擇 **/lambdav1** 資源，然後選擇**建立方法**。

   然後，執行下列動作：

   1. 針對**方法類型**，選取 **GET**。

   1. 針對**整合類型**，選取 **Lambda 函數**。

   1. 將 **Lambda 代理整合**保持關閉。

   1. 對於 **Lambda function** (Lambda 函數)，請輸入 `${stageVariables.function}`。  
![\[建立與 Lambda 函數整合的 GET 方法，如 function 階段變數所指定。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/stageVariables-new-console-create-lambda-get-method.png)
**提示**  
出現輸入**新增許可命令**的提示時，複製 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令。對將要指派至 `function` 階段變數的每個 Lambda 函數執行命令。例如，如果 `$stageVariables.function` 值為 `HelloWorld`，則執行下列 AWS CLI 命令：  

      ```
      aws lambda add-permission --function-name arn:aws:lambda:us-east-1:account-id:function:HelloWorld --source-arn arn:aws:execute-api:us-east-1:account-id:api-id/*/GET/lambdav1 --principal apigateway.amazonaws.com --statement-id statement-id-guid --action lambda:InvokeFunction
      ```
 如果不執行此作業，會在呼叫方法時造成 `500 Internal Server Error` 回應。將 `${stageVariables.function}` 取代為指派給階段變數的 Lambda 函數名稱。  
   

![\[AWS CLI 命令將許可新增至 Lambda 函數，以供您建立的 方法叫用。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/stageVariables-new-console-add-permission-to-lambda-function.png)


   1. 選擇**建立方法**。

1. 將 API 同時部署到 **prod** 和 **beta** 階段。

1. 在主導覽窗格中，選擇**階段**。在 **Stages (階段)** 導覽窗格中，選擇 **beta**。在**階段詳細資訊**下，選擇複製圖示以複製您的 API 的調用 URL，然後在 Web 瀏覽器中輸入您的 API 調用 URL。將 **/lambdav1** 附加至 URL，再按下 Enter 鍵。

   您會收到以下回應。

   ```
   "Hello, World! I'm not sure where I'm calling from..."
   ```

## 透過階段變數將階段特定中繼資料傳送到 Lambda 函數
<a name="pass-version-info-to-lambda-backend-with-stage-variable"></a>

此程序說明如何使用階段變數將階段特定組態中繼資料傳送到 Lambda 函數。您使用之前宣告的 `stageName` 階段變數，建立 `POST` 方法並輸入對應範本來產生承載。

**透過階段變數將階段特定中繼資料傳送到 Lambda 函數**

1. 選擇 **/lambdav1** 資源，然後選擇**建立方法**。

   然後，執行下列動作：

   1. 針對**方法類型**，選取 **POST**。

   1. 針對**整合類型**，選取 **Lambda 函數**。

   1. 將 **Lambda 代理整合**保持關閉。

   1. 對於 **Lambda function** (Lambda 函數)，請輸入 `${stageVariables.function}`。

   1. 出現輸入**新增許可命令**的提示時，複製 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令。對將要指派至 `function` 階段變數的每個 Lambda 函數執行命令。

   1. 選擇**建立方法**。

1. 選擇**整合請求**索引標籤，然後在**整合請求設定**區段中，選擇**編輯**。

1. 選擇**對應範本**，然後選擇**新增對應範本**。

1. 針對**內容類型**，輸入 **application/json**。

1. 針對**範本內文**，輸入下列範本：

   ```
   #set($inputRoot = $input.path('$'))
   {
       "stageName" : "$stageVariables.stageName"
   }
   ```
**注意**  
 在對應範本中，必須在有引號 (如 `"$stageVariables.stageName"` 或 `"${stageVariables.stageName}"`) 的情況下參照階段變數。在其他地方，則必須在沒有引號的情況下參照 (如 `${stageVariables.function}` 所示)。

1. 選擇**儲存**。

1. 將 API 同時部署到 **beta** 和 **prod** 階段。

1. 若要使用 REST API 用戶端傳遞階段特定的中繼資料，請執行下列動作：

   1. 在 **Stages (階段)** 導覽窗格中，選擇 **beta**。在**階段詳細資訊**下，選擇複製圖示以複製您的 API 的調用 URL，然後在 REST API 用戶端的輸入欄位中輸入您的 API 調用 URL。附加 **/lambdav1**，然後再提交請求。

      您會收到以下回應。

      ```
      "Hello, World! I'm calling from the beta stage."
      ```

   1. 在**階段**導覽窗格中，選擇 **prod**。在**階段詳細資訊**下，選擇複製圖示以複製您的 API 的調用 URL，然後在 REST API 用戶端的輸入欄位中輸入您的 API 調用 URL。附加 **/lambdav1**，然後再提交請求。

      您會收到以下回應。

      ```
      "Hello, World! I'm calling from the prod stage."
      ```

1. 若要使用**測試**功能來傳遞階段特定的中繼資料，請執行下列動作：

   1. 在**資源**導覽窗格中，選擇**測試**索引標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

   1. 針對 **function**，輸入 **HelloWorld**。

   1. 針對 **stageName**，輸入 **beta**。

   1. 選擇**測試**。您不需要新增內文至您的 `POST` 請求。

      您會收到以下回應。

      ```
      "Hello, World! I'm calling from the beta stage."
      ```

   1. 您可以重複前述步驟來測試 **Prod** 階段。針對 **stageName**，輸入 **Prod**。

      您會收到以下回應。

      ```
      "Hello, World! I'm calling from the prod stage."
      ```

# API Gateway 中 REST API 的 API Gateway 階段變數參考
<a name="aws-api-gateway-stage-variables-reference"></a>

 在下列情況下，您可以使用 API Gateway 階段變數。

## 參數對應表達式
<a name="stage-variables-in-parameter-mapping-expressions"></a>

階段變數可用在 API 方法請求或回應標頭參數的參數映射表達式中，沒有任何部分替換。在下列範例中，階段變數參考不使用 `$` 與包圍的 `{...}`。
+ `stageVariables.<variable_name>`

## 對應範本
<a name="stage-variables-in-mapping-templates"></a>

 階段變數可以用在對應範本的任何位置，如下例所示。
+  `{ "name" : "$stageVariables.<variable_name>"}`
+ `{ "name" : "${stageVariables.<variable_name>}"}`

## HTTP 整合 URI
<a name="stage-variables-in-integration-HTTP-uris"></a>

階段變數可用作 HTTP 整合 URL 的一部分，如下例所示。
+ 不含通訊協定的完整 URI – `http://${stageVariables.<variable_name>}`
+ 完整的網域 – `http://${stageVariables.<variable_name>}/resource/operation`
+ 子網域 – `http://${stageVariables.<variable_name>}.example.com/resource/operation`
+ 路徑 – `http://example.com/${stageVariables.<variable_name>}/bar`
+ 查詢字串 – `http://example.com/foo?q=${stageVariables.<variable_name>}` 

## AWS 整合 URIs
<a name="stage-variables-in-integration-aws-uris"></a>

 階段變數可以用作 AWS URI 動作或路徑元件的一部分，如下列範例所示。
+ `arn:aws:apigateway:<region>:<service>:${stageVariables.<variable_name>}`

## AWS 整合 URIs(Lambda 函數）
<a name="stage-variables-in-integration-lambda-functions"></a>

 階段變數可用來取代 Lambda 函數名稱或版本/別名，如下例所示。
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations`
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations`

**注意**  
若要使用 Lambda 函數的階段變數，函數必須與 API 位於相同的帳戶中。階段變數不支援跨帳戶 Lambda 函數。

## Amazon Cognito 使用者集區
<a name="stage-variables-in-integration-lambda-functions"></a>

階段變數可用來取代 `COGNITO_USER_POOLS` 授權方的 Amazon Cognito 使用者集區。
+ `arn:aws:cognito-idp:<region>:<account_id>:userpool/${stageVariables.<variable_name>}`

## AWS 整合憑證
<a name="stage-variables-in-integration-aws-credentials"></a>

 階段變數可以用作 AWS 使用者/角色登入資料 ARN 的一部分，如下列範例所示。
+  `arn:aws:iam::<account_id>:${stageVariables.<variable_name>}` 