

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

# Amazon API Gateway REST API 教學課程
<a name="api-gateway-rest-tutorials"></a>

下列教學課程提供實作練習以協助您了解 API Gateway REST API。

**Topics**
+ [

# 選擇 AWS Lambda 整合教學課程
](getting-started-with-lambda-integration.md)
+ [

# 教學課程：匯入範例來建立 REST API
](api-gateway-create-api-from-example.md)
+ [

# 選擇 HTTP 整合教學課程
](getting-started-http-integrations.md)
+ [

# 教學：建立具私有整合的 REST API
](getting-started-with-private-integration.md)
+ [

# 教學課程：使用 AWS 整合建立 REST API
](getting-started-aws-proxy.md)
+ [

# 教學課程：建立具有兩個 AWS 服務整合和一個 Lambda 非代理整合的計算器 REST API
](integrating-api-with-aws-services-lambda.md)
+ [

# 教學：建立 REST API 做為 Amazon S3 代理
](integrating-api-with-aws-services-s3.md)
+ [

# 教學課程：建立 REST API 做為 Amazon Kinesis 代理
](integrating-api-with-aws-services-kinesis.md)
+ [

# 教學課程：使用 AWS SDKs或 建立 REST API AWS CLI
](api-gateway-create-api-cli-sdk.md)
+ [

# 教學：建立私有 REST API
](private-api-tutorial.md)

# 選擇 AWS Lambda 整合教學課程
<a name="getting-started-with-lambda-integration"></a>

 若要建置具有 Lambda 整合的 API，您可以使用 Lambda 代理整合或 Lambda 非代理整合。

在 Lambda 代理整合中，Lambda 函數的輸入可以表示為的請求標頭、路徑變數、查詢字串參數和 API 組態資料的任何組合。您只需選擇 Lambda 函數。API Gateway 會設定整合請求和整合回應。設定之後，API 方法可以在不修改現有設定的情況下不斷演進。這是可能的，因為後端 Lambda 函數會剖析傳入的請求資料，並回應用戶端。

在 Lambda 非代理整合中，您必須確保將 Lambda 函數的輸入提供為整合請求承載。您必須將用戶端提供為請求參數的任何輸入資料，映射至適當的整合請求內文。您也可能需要將用戶端提供的請求內文翻譯為 Lambda 函數可辨識的格式。

在 Lambda 代理或 Lambda 非代理整合中，您可以在與您建立 API 的帳戶不同的帳戶中使用 Lambda 函數。

**Topics**
+ [

# 教學：建立具 Lambda 代理整合的 REST API
](api-gateway-create-api-as-simple-proxy-for-lambda.md)
+ [

# 教學：建立具 Lambda 非代理整合的 REST API
](getting-started-lambda-non-proxy-integration.md)
+ [

# 教學：建置具 cross-account Lambda 代理整合的 REST API
](apigateway-cross-account-lambda-integrations.md)

# 教學：建立具 Lambda 代理整合的 REST API
<a name="api-gateway-create-api-as-simple-proxy-for-lambda"></a>

[Lambda 代理整合](set-up-lambda-proxy-integrations.md)是一種輕量型彈性 API Gateway API 整合類型，可讓您整合 API 方法 (或整個 API) 與 Lambda 函數。Lambda 函數的編寫方式可以是 [Lambda 支援的任何語言](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)。因為它是代理整合，所以您可以隨時變更 Lambda 函數實作，無需重新部署您的 API。

在此教學中，您將執行下列操作：
+ 建立 "Hello, World\$1" Lambda 函數作為 API 的後端。
+ 建立和測試 具有 Lambda 代理整合的 API。

**Topics**
+ [

## 建立 "Hello, World\$1" Lambda 函式
](#api-gateway-proxy-integration-create-lambda-backend)
+ [

## 建立 "Hello, World\$1" API
](#api-gateway-create-api-as-simple-proxy-for-lambda-build)
+ [

## 部署和測試 API
](#api-gateway-create-api-as-simple-proxy-for-lambda-test)

## 建立 "Hello, World\$1" Lambda 函式
<a name="api-gateway-proxy-integration-create-lambda-backend"></a>

**建立 "Hello, World\$1" Lambda 控制台中的 Lambda 函數**

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

1. 在 AWS 導覽列上，選擇 [AWS 區域](https://docs.aws.amazon.com/general/latest/gr/apigateway.html)。
**注意**  
記下您建立 Lambda 函數的區域。在建立 API 時，您將需要此區域。

1. 在導覽窗格中，選擇 **Functions (函數)**。

1. 選擇 **Create function (建立函數)**。

1. 選擇 **Author from scratch** (從頭開始撰寫)。

1. 在 **Basic information (基本資訊)** 下，請執行下列動作：

   1. 在**函數名稱** 中，輸入 **GetStartedLambdaProxyIntegration**。

   1. 針對**執行期**，請選擇最新支援的 **Node.js** 或 **Python** 執行期。

   1. 對於**架構**，請保留預設設定。

   1. 在**許可**下，展開**變更預設執行角色**。從**執行角色**下拉式清單中，選擇**從 AWS 政策範本建立新角色**。

   1. 在**角色名稱** 中，輸入 **GetStartedLambdaBasicExecutionRole**。

   1. 將 **Policy templates (政策範本)** 欄位留白。

   1. 選擇 **Create function (建立函數)**。

1. 在內嵌程式碼編輯器的 **Function code (函數程式碼)** 下，複製/貼上下列程式碼：

------
#### [ Node.js ]

   ```
   export const handler = async(event, context) => {
       console.log('Received event:', JSON.stringify(event, null, 2));
       var res ={
           "statusCode": 200,
           "headers": {
               "Content-Type": "*/*"
           }
       };
       var greeter = 'World';
       if (event.greeter && event.greeter!=="") {
           greeter =  event.greeter;
       } else if (event.body && event.body !== "") {
           var body = JSON.parse(event.body);
           if (body.greeter && body.greeter !== "") {
               greeter = body.greeter;
           }
       } else if (event.queryStringParameters && event.queryStringParameters.greeter && event.queryStringParameters.greeter !== "") {
           greeter = event.queryStringParameters.greeter;
       } else if (event.multiValueHeaders && event.multiValueHeaders.greeter && event.multiValueHeaders.greeter != "") {
           greeter = event.multiValueHeaders.greeter.join(" and ");
       } else if (event.headers && event.headers.greeter && event.headers.greeter != "") {
           greeter = event.headers.greeter;
       } 
       res.body = "Hello, " + greeter + "!";
       return res
   };
   ```

------
#### [ Python ]

   ```
   import json
   
   
   def lambda_handler(event, context):
       print(event)
   
       greeter = 'World'
   
       try:
           if (event['queryStringParameters']) and (event['queryStringParameters']['greeter']) and (
                   event['queryStringParameters']['greeter'] is not None):
               greeter = event['queryStringParameters']['greeter']
       except KeyError:
           print('No greeter')
   
       try:
           if (event['multiValueHeaders']) and (event['multiValueHeaders']['greeter']) and (
                   event['multiValueHeaders']['greeter'] is not None):
               greeter = " and ".join(event['multiValueHeaders']['greeter'])
       except KeyError:
           print('No greeter')
   
       try:
           if (event['headers']) and (event['headers']['greeter']) and (
                   event['headers']['greeter'] is not None):
               greeter = event['headers']['greeter']
       except KeyError:
           print('No greeter')
   
       if (event['body']) and (event['body'] is not None):
           body = json.loads(event['body'])
           try:
               if (body['greeter']) and (body['greeter'] is not None):
                   greeter = body['greeter']
           except KeyError:
               print('No greeter')
   
       res = {
           "statusCode": 200,
           "headers": {
               "Content-Type": "*/*"
           },
           "body": "Hello, " + greeter + "!"
       }
   
       return res
   ```

------

1. 選擇 **Deploy (部署)**。

## 建立 "Hello, World\$1" API
<a name="api-gateway-create-api-as-simple-proxy-for-lambda-build"></a>

立即為您的 "Hello, World\$1" 建立 API 使用 API Gateway 主控台的 Lambda 函數。

**建立 "Hello, World\$1" API**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇**組建**。

1.  對於**API 名稱**，輸入 **LambdaProxyAPI**。

1. 在**描述**，請輸入描述。

1. 將 **API 端點類型**保持設定為**區域**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇**建立 API**。

在建立 API 之後，請建立資源。一般而言，會根據應用程式邏輯將 API 資源組織為資源樹狀結構。在此範例中，您會建立 **/helloworld** 資源。

**建立資源**

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

1. 讓**代理資源**保持關閉。

1. 將**資源路徑**保持為 `/`。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

 在代理整合中，透過一個代表任何 HTTP 方法的囊括型 `ANY` 方法，將整個請求按現狀傳送到後端 Lambda 函數。實際的 HTTP 方法由用戶端在執行時間指定。`ANY` 方法可讓使用針對所有支援的 HTTP 方法而設定的單一 API 方法：`DELETE`、`GET`、`HEAD`、`OPTIONS`、`PATCH`、`POST` 和 `PUT`。

**建立 `ANY` 方法**

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

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

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

1. 開啟 **Lambda 代理整合**。

1. 針對 **Lambda 函數**，選取您建立 Lambda 函數 AWS 區域 的 ，然後輸入函數名稱。

1. 若要使用 29 秒的預設逾時值，請將**預設逾時**保持開啟。若要設定自訂逾時，請選擇**預設逾時**，然後輸入介於 `50` 和 `29000` 毫秒之間的逾時值。

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

## 部署和測試 API
<a name="api-gateway-create-api-as-simple-proxy-for-lambda-test"></a>

**部署 API**

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **test**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

1. 在**階段詳細資訊**下，選擇複製圖示以複製 API 的調用 URL。

### 使用瀏覽器和 cURL 來測試具有 Lambda 代理整合的 API
<a name="api-gateway-create-api-as-simple-proxy-for-lambda-test-curl"></a>

您可以使用瀏覽器或 [cURL](https://curl.se/) 來測試您的 API。

若要僅使用查詢字串參數來測試 `GET` 請求，您可以將 API `helloworld` 資源的 URL 輸入至瀏覽器位址列。

若要建立適用於 API `helloworld` 資源的 URL，請將資源 `helloworld` 和查詢字串參數 `?greeter=John` 附加至您的調用 URL。您的 URL 看起來應該如下所示。

```
https://r275xc9bmd.execute-api.us-east-1.amazonaws.com/test/helloworld?greeter=John
```

針對其他方法，您必須使用更進階的 REST API 測試公用程式，例如 [POSTMAN](https://www.postman.com/) 或 [cURL](https://curl.se/)。本教學使用 cURL。以下 cURL 命令範例假設 cURL 已安裝在您的電腦上。

**若要使用 cURL 測試已部署的 API：**

1. 開啟終端機視窗。

1. 複製以下 cURL 命令並將它貼到終端視窗，然後將調用 URL 取代為您在上一個步驟中複製的 URL，再將 **/helloworld** 新增至該 URL 的結尾。
**注意**  
如果您是在 Windows 上執行命令，請改用此語法：  

   ```
   curl -v -X POST "https://r275xc9bmd.execute-api.us-east-1.amazonaws.com/test/helloworld" -H "content-type: application/json" -d "{ \"greeter\": \"John\" }"
   ```

   1. 使用查詢字串參數 `?greeter=John` 呼叫 API：

      ```
      curl -X GET 'https://r275xc9bmd.execute-api.us-east-1.amazonaws.com/test/helloworld?greeter=John'
      ```

   1. 使用標頭參數 `greeter:John` 呼叫 API：

      ```
      curl -X GET https://r275xc9bmd.execute-api.us-east-1.amazonaws.com/test/helloworld \
        -H 'content-type: application/json' \
        -H 'greeter: John'
      ```

   1. 使用內文 `{"greeter":"John"}` 呼叫 API：

      ```
      curl -X POST https://r275xc9bmd.execute-api.us-east-1.amazonaws.com/test/helloworld \
        -H 'content-type: application/json' \
        -d '{ "greeter": "John" }'
      ```

   在所有情況下，輸出都是具有下列回應內文的 200 回應：

   ```
   Hello, John!
   ```

# 教學：建立具 Lambda 非代理整合的 REST API
<a name="getting-started-lambda-non-proxy-integration"></a>

在此演練中，我們使用 API Gateway 主控台建置一個 API，讓用戶端可以透過 Lambda 非代理整合 (也稱為自訂整合) 呼叫 Lambda 函數。如需有關 AWS Lambda 和 Lambda 函數的詳細資訊，請參閱 [AWS Lambda 開發人員指南](https://docs.aws.amazon.com/lambda/latest/dg/)。

為方便學習，我們選擇了一個具有最少 API 設定的簡單 Lambda 函數，以逐步引導您建置具有 Lambda 自訂整合的 API Gateway API。必要時，我們會說明一些邏輯。如需 Lambda 自訂整合的更詳細範例，請參閱[教學課程：建立具有兩個 AWS 服務整合和一個 Lambda 非代理整合的計算器 REST API](integrating-api-with-aws-services-lambda.md)。

建立 API 之前，請在 AWS Lambda中建立 Lambda 函數來設定 Lambda 後端，以下將進行說明。

**Topics**
+ [

## 為 Lambda 非代理整合建立 Lambda 函數
](#getting-started-new-lambda)
+ [

## 建立具有 Lambda 非代理整合的 API
](#getting-started-new-api)
+ [

## 測試呼叫 API 方法
](#getting-started-new-get)
+ [

## 部署 API
](#getting-started-deploy-api)
+ [

## 在部署階段測試 API
](#getting-started-test)
+ [

## 清除
](#getting-started-clean-up)

## 為 Lambda 非代理整合建立 Lambda 函數
<a name="getting-started-new-lambda"></a>

**注意**  
建立 Lambda 函數可能會導致 AWS 您的帳戶產生費用。

 在此步驟中，您會為 Lambda 自訂整合建立 "Hello, World\$1" 之類的 Lambda 函數。在此演練中，此函數稱為 `GetStartedLambdaIntegration`。

 以下是此 `GetStartedLambdaIntegration` Lambda 函數的實作：

------
#### [ Node.js ]

```
'use strict';
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];            
var times = ['morning', 'afternoon', 'evening', 'night', 'day'];

export const handler = async(event) => {
  console.log(event);
  // Parse the input for the name, city, time and day property values
  let name = event.name === null || event.name === undefined || event.name === "" ? 'you' : event.name;
  let city = event.city === undefined ? 'World' : event.city;
  let time = times.indexOf(event.time)<0 ? 'day' : event.time;
  let day = days.indexOf(event.day)<0 ? null : event.day;

  // Generate a greeting
  let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. ';
  if (day) greeting += 'Happy ' + day + '!';
  
  // Log the greeting to CloudWatch
  console.log('Hello: ', greeting);
  
  // Return a greeting to the caller
  return {"greeting": greeting}
};
```

------
#### [ Python ]

```
import json

days = {
    'Sunday',
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday'}
times = {'morning', 'afternoon', 'evening', 'night', 'day'}


def lambda_handler(event, context):
    print(event)
    # parse the input for the name, city, time, and day property values
    name = event.get("name") or 'you'
    city = event.get("city") or 'World'
    try:
        if event['time'] in times:
            time = event['time']
        else:
            time = 'day'
    except KeyError:
        time = 'day'
    try:
        if event['day'] in days:
            day = event['day']
        else:
            day = ''
    except KeyError:
        day = ''
    # Generate a greeting
    greeting = 'Good ' + time + ', ' + name + ' of ' + \
        city + '.' + ['', ' Happy ' + day + '!'][day != '']
    # Log the greeting to CloudWatch
    print(greeting)

    # Return a greeting to the caller
    return {"greeting": greeting}
```

------

對於 Lambda 自訂整合，API Gateway 會從用戶端傳遞 Lambda 函數的輸入作為整合請求內文。此輸入是 Lambda 函數處理常式的 `event` 物件。

我們的 Lambda 函數很簡單。它會剖析 `event`、`name`、`city` 與 `time` 屬性的輸入 `day` 物件。然後，它會傳回問候語 (以 `{"message":greeting}` 的 JSON 物件形式) 給發起人。該訊息的模式為 `"Good [morning|afternoon|day], [name|you] in [city|World]. Happy day!"`。它假設 Lambda 函數的輸入屬於下列 JSON 物件：

```
{
  "city": "...",
  "time": "...",
  "day": "...",
  "name" : "..."
}
```

如需詳細資訊，請參閱 [AWS Lambda 開發人員指南](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html)。

此外，此函數會藉由呼叫 `console.log(...)` 將其執行記錄到 Amazon CloudWatch。這有助於在偵錯函數時追蹤呼叫。若要允許 `GetStartedLambdaIntegration` 函數記錄呼叫，請使用適當的政策來設定 IAM 角色，讓 Lambda 函數可以建立 CloudWatch 串流並將日誌項目新增至串流。Lambda 主控台會引導您建立必要的 IAM 角色與政策。

如果您未使用 API Gateway 主控台設定 API (例如[從 OpenAPI 檔案匯入 API](https://github.com/aws-samples/api-gateway-secure-pet-store/blob/master/src/main/resources/swagger.yaml#L39) 時)，您必須明確建立 (如果需要) 並設定叫用角色與政策，API Gateway 才能叫用 Lambda 函數。如需如何為 API Gateway API 設定 Lambda 呼叫與執行角色的詳細資訊，請參閱[使用 IAM 許可權控制 REST API 的存取](permissions.md)。

 相較於 `GetStartedLambdaProxyIntegration` (Lambda 代理整合的 Lambda 函數)，`GetStartedLambdaIntegration` (Lambda 自訂整合的 Lambda 函數) 只會接受來自 API Gateway API 整合請求內文的輸入。該函數可以傳回任何 JSON 物件、字串、數值、布林值，或甚至是二進位 Blob 的輸出。相較之下，Lambda 代理整合的 Lambda 函數可以接受來自任何請求資料的輸入，但必須傳回特定 JSON 物件的輸出。Lambda 自訂整合的 `GetStartedLambdaIntegration` 函數可以接受 API 請求參數作為輸入，但前提是 API Gateway 在將用戶端請求轉送到後端之前，已將必要的 API 請求參數對應到整合請求內文。若要這樣做，API 開發人員必須建立對應範本，並在建立 API 時於 API 方法上設定此範本。

現在，建立 `GetStartedLambdaIntegration` Lambda 函數。

**建立 Lambda 自訂整合的 `GetStartedLambdaIntegration` Lambda 函數**

1. 在 https：//[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 開啟 AWS Lambda 主控台。

1. 執行以下任意一項：
   + 出現歡迎頁面時，請選擇 **Get Started Now (立即開始使用)**，然後選擇 **Create function (建立函數)**。
   + 出現 **Lambda > Functions (Lambda > 函數)** 清單頁面時，請選擇 **Create function (建立函數)**。

1. 選擇 **Author from scratch** (從頭開始撰寫)。

1. 在 **Author from scratch (從頭開始撰寫)** 窗格上，執行下列操作：

   1. 在**名稱**，輸入 **GetStartedLambdaIntegration** 做為 Lambda 函數名稱。

   1. 針對**執行期**，請選擇最新支援的 **Node.js** 或 **Python** 執行期。

   1. 對於**架構**，請保留預設設定。

   1. 在**許可**下，展開**變更預設執行角色**。從**執行角色**下拉式清單中，選擇**從 AWS 政策範本建立新角色**。

   1. 在**角色名稱**中輸入角色名稱 (例如 **GetStartedLambdaIntegrationRole**)。

   1. 對於 **Policy templates (政策範本)**，選擇 **Simple microservice permissions (簡易微服務許可)**。

   1. 選擇 **Create function (建立函數)**。

1. 在 **Configure function (設定函數)** 窗格的 **Function code (函數程式碼)** 中，執行下列操作：

   1. 將本節開頭列出的 Lambda 函數程式碼複製並貼到內嵌程式碼編輯器。

   1. 對於此區段中的所有其他欄位，則保留預設選項。

   1. 選擇 **Deploy (部署)**。

1. 若要測試新建立的函數，請選擇**測試**索引標籤。

   1. **事件名稱**輸入 **HelloWorldTest**。

   1. 對於**事件 JSON**，請使用下列命令取代預設程式碼。

      ```
      {
        "name": "Jonny",
        "city": "Seattle",
        "time": "morning",
        "day": "Wednesday"
      }
      ```

   1.  選擇**測試**以呼叫函數。**執行結果：成功**區段會隨即顯示。展開**詳細資訊**，您會看到下列輸出。

      ```
      {
          "greeting": "Good morning, Jonny of Seattle. Happy Wednesday!"
      }
      ```

      該輸出也會寫入 CloudWatch Logs。

 作為附帶練習，您可使用 IAM 主控台來檢視 Lambda 函數建立過程中所建立的 IAM 角色 (`GetStartedLambdaIntegrationRole`)。此 IAM 角色會附加兩個內嵌政策。其中一個規定 Lambda 執行的最基本許可。它允許在建立 Lambda 函數的區域中，對您帳戶的任何 CloudWatch 資源呼叫 CloudWatch `CreateLogGroup`。此政策也允許建立 `GetStartedLambdaIntegration` Lambda 函數的 CloudWatch 串流與記錄日誌事件。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:us-east-1:111111111111:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:us-east-1:111111111111:log-group:/aws/lambda/GetStartedLambdaIntegration:*"
            ]
        }
    ]
}
```

------

另一個政策文件適用於叫用此範例中 AWS 未使用的其他服務。您目前可以略過。

 IAM 角色與信任實體相關聯，也就是 `lambda.amazonaws.com`。以下是信任關係：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

 此信任關係與內嵌政策的組合可讓 Lambda 函數叫用 `console.log()` 函數來將事件記錄到 CloudWatch Logs。

## 建立具有 Lambda 非代理整合的 API
<a name="getting-started-new-api"></a>

 建立並測試 Lambda 函數 (`GetStartedLambdaIntegration`) 之後，您就可以透過 API Gateway API 公開函數。為了方便說明，我們會透過泛型 HTTP 方法公開 Lambda 函數。我們使用請求內文、URL 路徑變數、查詢字串與標頭，從用戶端接收必要的輸入資料。我們開啟 API 的 API Gateway 請求驗證程式，確保所有必要的資料都已正確定義與指定。我們設定對應範本，讓 API Gateway 可以將用戶端提供的請求資料轉換成後端 Lambda 函數所需的有效格式。

**建立具有 Lambda 非代理整合的 API**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇**組建**。

1.  對於**API 名稱**，輸入 **LambdaNonProxyAPI**。

1. 在**描述**，請輸入描述。

1. 將 **API 端點類型**保持設定為**區域**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇**建立 API**。

建立 API 之後，請建立 **/\$1city\$1** 資源。這是具有路徑變數的資源範例，其會接受來自用戶端的輸入。稍後，您會使用對應範本將此路徑變數對應到 Lambda 函數輸入。

**建立資源**

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

1. 讓**代理資源**保持關閉。

1. 將**資源路徑**保持為 `/`。

1. 針對**資源名稱**，輸入 **\$1city\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

在建立 **/\$1city\$1** 資源後，請建立 `ANY` 方法。`ANY` HTTP 動詞是用戶端在執行時間提交之有效 HTTP 方法的預留位置。此範例顯示 `ANY` 方法可用於 Lambda 自訂整合以及 Lambda 代理整合。

**建立 `ANY` 方法**

1. 選取 **/\$1city\$1** 資源，然後選擇**建立方法**。

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

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

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

1. 針對 **Lambda 函數**，選取您建立 Lambda 函數 AWS 區域 的 ，然後輸入函數名稱。

1. 選擇**方法請求設定**。

   此時，請開啟 URL 路徑變數、查詢字串參數與標頭的請求驗證程式，以確保所有必要的資料都已定義。在此範例中，您會建立 `time` 查詢字串參數和 `day` 標頭。

1. 對於**請求驗證程式**，選取**驗證查詢字串參數與標頭**。

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

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

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

   1. 開啟**必要**。

   1. 讓**快取**保持關閉。

1. 選擇 **HTTP 請求標頭**，然後執行下列動作：

   1. 選擇**新增標頭**。

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

   1. 開啟**必要**。

   1. 讓**快取**保持關閉。

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

開啟請求驗證程式之後，請根據後端 Lambda 函數的要求，新增內文對應範本將傳入請求轉換為 JSON 承載，以設定 `ANY` 方法的整合請求。

**設定整合請求**

1. 在**整合請求**標籤上，於**整合請求設定**下，選擇**編輯**。

1. 針對**請求內文傳遞**，選取**未定義範本時 (建議)**。

1. 選擇**對應範本**。

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

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

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

   ```
   #set($inputRoot = $input.path('$'))
   {
     "city": "$input.params('city')",
     "time": "$input.params('time')",
     "day":  "$input.params('day')",
     "name": "$inputRoot.callerName"
   }
   ```

1. 選擇**儲存**。

## 測試呼叫 API 方法
<a name="getting-started-new-get"></a>

 API Gateway 主控台提供測試功能，可讓您測試呼叫 API，再進行部署。您可以使用主控台的 Test (測試) 功能，透過提交下列請求來測試 API：

```
POST /Seattle?time=morning
day:Wednesday

{
    "callerName": "John"
}
```

 在此測試請求中，您會將 `ANY` 設定為 `POST`、將 `{city}` 設定為 `Seattle`、將 `Wednesday` 設定為 `day` 標頭值，並將 `"John"` 指派為 `callerName` 值。

**測試 `ANY` 方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

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

1. 針對**路徑**，在**城市**下輸入 **Seattle**。

1. 針對**查詢字串**，輸入 **time=morning**。

1. 針對**標頭**，輸入 **day:Wednesday**。

1. 針對**請求內文**，輸入 **\$1 "callerName": "John" \$1**。

1. 選擇**測試**。

遵循下列方式驗證所傳回的回應承載：

```
{
  "greeting": "Good morning, John of Seattle. Happy Wednesday!"
}
```

您也可以檢視日誌，查看 API Gateway 如何處理請求與回應。

```
Execution log for request test-request
Thu Aug 31 01:07:25 UTC 2017 : Starting execution for request: test-invoke-request
Thu Aug 31 01:07:25 UTC 2017 : HTTP Method: POST, Resource Path: /Seattle
Thu Aug 31 01:07:25 UTC 2017 : Method request path: {city=Seattle}
Thu Aug 31 01:07:25 UTC 2017 : Method request query string: {time=morning}
Thu Aug 31 01:07:25 UTC 2017 : Method request headers: {day=Wednesday}
Thu Aug 31 01:07:25 UTC 2017 : Method request body before transformations: { "callerName": "John" }
Thu Aug 31 01:07:25 UTC 2017 : Request validation succeeded for content type application/json
Thu Aug 31 01:07:25 UTC 2017 : Endpoint request URI: https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:GetStartedLambdaIntegration/invocations
Thu Aug 31 01:07:25 UTC 2017 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************338c72, X-Amz-Date=20170831T010725Z, x-amzn-apigateway-api-id=beags1mnid, X-Amz-Source-Arn=arn:aws:execute-api:us-west-2:123456789012:beags1mnid/null/POST/{city}, Accept=application/json, User-Agent=AmazonAPIGateway_beags1mnid, X-Amz-Security-Token=FQoDYXdzELL//////////wEaDMHGzEdEOT/VvGhabiK3AzgKrJw+3zLqJZG4PhOq12K6W21+QotY2rrZyOzqhLoiuRg3CAYNQ2eqgL5D54+63ey9bIdtwHGoyBdq8ecWxJK/YUnT2Rau0L9HCG5p7FC05h3IvwlFfvcidQNXeYvsKJTLXI05/yEnY3ttIAnpNYLOezD9Es8rBfyruHfJfOqextKlsC8DymCcqlGkig8qLKcZ0hWJWVwiPJiFgL7laabXs++ZhCa4hdZo4iqlG729DE4gaV1mJVdoAagIUwLMo+y4NxFDu0r7I0/EO5nYcCrppGVVBYiGk7H4T6sXuhTkbNNqVmXtV3ch5bOlh7 [TRUNCATED]
Thu Aug 31 01:07:25 UTC 2017 : Endpoint request body after transformations: {
  "city": "Seattle",
  "time": "morning",
  "day": "Wednesday",
  "name" : "John"
}
Thu Aug 31 01:07:25 UTC 2017 : Sending request to https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:GetStartedLambdaIntegration/invocations
Thu Aug 31 01:07:25 UTC 2017 : Received response. Integration latency: 328 ms
Thu Aug 31 01:07:25 UTC 2017 : Endpoint response body before transformations: {"greeting":"Good morning, John of Seattle. Happy Wednesday!"}
Thu Aug 31 01:07:25 UTC 2017 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=c0475a28-8de8-11e7-8d3f-4183da788f0f, Connection=keep-alive, Content-Length=62, Date=Thu, 31 Aug 2017 01:07:25 GMT, X-Amzn-Trace-Id=root=1-59a7614d-373151b01b0713127e646635;sampled=0, Content-Type=application/json}
Thu Aug 31 01:07:25 UTC 2017 : Method response body after transformations: {"greeting":"Good morning, John of Seattle. Happy Wednesday!"}
Thu Aug 31 01:07:25 UTC 2017 : Method response headers: {X-Amzn-Trace-Id=sampled=0;root=1-59a7614d-373151b01b0713127e646635, Content-Type=application/json}
Thu Aug 31 01:07:25 UTC 2017 : Successfully completed execution
Thu Aug 31 01:07:25 UTC 2017 : Method completed with status: 200
```

日誌會顯示對應前的傳入請求，以及對應後的整合請求。測試失敗時，日誌可用於評估原始輸入是否正確或對應範本是否正常運作。

## 部署 API
<a name="getting-started-deploy-api"></a>

 測試呼叫是一種模擬並有所限制。例如，它會略過 API 上所制定的任何授權機制。若要即時測試 API 執行，您必須先部署 API。若要部署 API，請建立一個階段來建立 API 在當時的快照。階段名稱也會定義 API 預設主機名稱後面的基底路徑。API 的根資源會附加在階段名稱後面。當您修改 API 時，您必須將它重新部署到新的或現有的階段，變更才會生效。

**將 API 部署到階段**

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **test**。
**注意**  
輸入必須為 UTF-8 編碼 (例如未本地化的) 文字。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

在**階段詳細資訊**下，選擇複製圖示以複製 API 的調用 URL。API 基底 URL 的一般模式為 `https://api-id.region.amazonaws.com/stageName`。例如，在 `beags1mnid` 區域中建立並部署到 `us-west-2` 階段之 API (`test`) 的基底 URL 為 `https://beags1mnid.execute-api.us-west-2.amazonaws.com/test`。

## 在部署階段測試 API
<a name="getting-started-test"></a>

您有數種方式可以測試已部署的 API。針對僅使用 URL 路徑變數或查詢字串參數的 GET 請求，您可以在瀏覽器中輸入 API 資源 URL。針對其他方法，您必須使用更進階的 REST API 測試公用程式，例如 [POSTMAN](https://www.postman.com/) 或 [cURL](https://curl.se/)。

**使用 cURL 測試 API**

1. 在連線至網際網路的本機電腦上，開啟終端機視窗。

1. 若要測試 `POST /Seattle?time=evening`：

   複製下列 cURL 命令並將其貼入終端機視窗。

   ```
   curl -v -X POST \
     'https://beags1mnid.execute-api.us-west-2.amazonaws.com/test/Seattle?time=evening' \
     -H 'content-type: application/json' \
     -H 'day: Thursday' \
     -H 'x-amz-docs-region: us-west-2' \
     -d '{
   	"callerName": "John"
   }'
   ```

   您應該取得具有下列承載的成功回應：

   ```
   {"greeting":"Good evening, John of Seattle. Happy Thursday!"}
   ```

   如果您在此方法請求中將 `POST` 變更為 `PUT`，您會取得相同的回應。

## 清除
<a name="getting-started-clean-up"></a>

若您不再需要因為此演練所建立的 Lambda 函數，可立即將其刪除。您也可以刪除隨附的 IAM 資源。

**警告**  
如果您打算完成本系列中的其他演練，則不要刪除 Lambda 執行角色或 Lambda 呼叫角色。如果刪除您 API 相依的 Lambda 函數，這些 API 將無法再運作。而刪除 Lambda 函數無法復原。所以若要再次使用該 Lambda 函數，必須加以重新建立。  
如果刪除 Lambda 函數相依的 IAM 資源，Lambda 函數將無法再運作，而且所有相依於該函數的 API 將無法再運作。IAM 資源一經刪除，即無法復原。所以若要再次使用該 IAM 資源，必須加以重新建立。

**若要刪除 Lambda 函數**

1. 登入 AWS 管理主控台 並在 https：//[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 開啟 AWS Lambda 主控台。

1. 從函數清單中選擇 **GetStartedLambdaIntegration**，然後依序選擇**動作**和**刪除函數**。出現提示時，再次選擇 **Delete (刪除)**。

**刪除相關聯的 IAM 資源**

1. 在以下網址開啟 IAM 主控台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 從 **Details (詳細資訊)** 中，選擇 **Roles (角色)**。

1. 從角色清單中選擇 **GetStartedLambdaIntegrationRole**，然後依序選擇**角色動作**和**刪除角色**。在主控台依照以下步驟刪除角色。

# 教學：建置具 cross-account Lambda 代理整合的 REST API
<a name="apigateway-cross-account-lambda-integrations"></a>

您現在可以使用來自不同 AWS 帳戶的 AWS Lambda 函數做為 API 整合後端。每個帳戶可以位於 Amazon API Gateway 可用的任何區域。這可讓您輕鬆地集中管理和分享跨多個 API 的 Lambda 後端函數。

在本節中，我們示範如何使用 Amazon API Gateway 主控台設定跨帳戶 Lambda 代理整合。

## 建立 API Gateway 跨帳戶 Lambda 整合的 API
<a name="apigateway-cross-account-lambda-integrations-create-api"></a>

**建立 API**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇**組建**。

1.  對於**API 名稱**，輸入 **CrossAccountLambdaAPI**。

1. 在**描述**，請輸入描述。

1. 將 **API 端點類型**保持設定為**區域**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇**建立 API**。

## 在另一個帳戶建立 Lambda 整合函數
<a name="apigateway-cross-account-lambda-integrations-create-lambda-function"></a>

現在您可以從與您在範例 API 中建立的不同帳戶建立 Lambda 函數。

**在另一個帳戶中建立 Lambda 函數**

1. 透過與您在 API Gateway API 中建立的不同的帳戶登入 Lambda 主控台。

1. 選擇 **Create function (建立函數)**。

1. 選擇 **Author from scratch** (從頭開始撰寫)。

1. 在 **Author from scratch (從頭開始撰寫)** 下，進行下列操作：

   1. 針對 **Function name (函數名稱)**，輸入名稱。

   1. 從 **Runtime (執行時間)** 下拉式清單中，選擇支援的 Node.js 執行時間。

   1. 對於**架構**，請保留預設設定。

   1. 在 **Permissions (許可)** 下，展開 **Choose or create an execution role (選擇或建立執行角色)**。您可以建立角色或選擇現有角色。

   1. 選擇 **Create function (建立函數)** 繼續。

1. 向下捲動到**函數程式碼** 窗格中。

1. 從 [教學：建立具 Lambda 代理整合的 REST API](api-gateway-create-api-as-simple-proxy-for-lambda.md) 輸入 Node.js 函數實作。

1. 選擇 **Deploy (部署)**。

1. 請注意適用於您函數的完整 ARN (在 Lambda 函數窗格的右上角)。在建立跨帳戶 Lambda 整合時會需要用到。

## 設定跨帳戶 Lambda 整合
<a name="apigateway-cross-account-lambda-integrations-create-integration2"></a>

在不同的帳戶有 Lambda 整合函數後，您可以使用 API Gateway 主控台在您的第一個帳戶將其新增至 API。

**注意**  
如果您設定的是跨區域、跨帳戶授權方，新增到目標函數的 `sourceArn` 應使用函數的區域，而非 API 的區域。

在建立 API 之後，請建立資源。一般而言，會根據應用程式邏輯將 API 資源組織為資源樹狀結構。在此範例中，您會建立 **/helloworld** 資源。

**建立資源**

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

1. 讓**代理資源**保持關閉。

1. 將**資源路徑**保持為 `/`。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

在建立資源之後，請建立 `GET` 方法。將 `GET` 方法與另一個帳戶中的 Lambda 函數整合。

**建立 `GET` 方法**

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

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

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

1. 開啟 **Lambda 代理整合**。

1. 針對 **Lambda 函數**，輸入步驟 1 中 Lambda 函數的完整 ARN。

   在 Lambda 主控台中，您可以在主控台視窗的右上角找到適用於您函數的 ARN。

1. 當您輸入 ARN 時，便會出現 `aws lambda add-permission` 命令字串。這個政策會授予您的第一個帳戶對第二個帳戶 Lambda 函數的存取權。將`aws lambda add-permission`命令字串複製並貼到為第二個帳戶設定的 AWS CLI 視窗中。

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

您可以在 Lambda 主控台中查看您的函數適用的更新政策。

**(選用) 查看更新的政策**

1. 登入 AWS 管理主控台 並在 https：//[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 開啟 AWS Lambda 主控台。

1. 選擇 Lambda 函數。

1. 選擇**許可**。

   您現在應該會看到內含 `Allow` 子句的 `Condition` 政策，其中 `AWS:SourceArn` 為您 API `GET` 方法的 ARN。

# 教學課程：匯入範例來建立 REST API
<a name="api-gateway-create-api-from-example"></a>

您可以使用 Amazon API Gateway 主控台，利用 HTTP 整合，針對 PetStore 網站建立和測試簡單的 REST API。API 定義會預先設定為 OpenAPI 2.0 檔案。將 API 定義載入至 API Gateway 之後，您可以使用 API Gateway 主控台來檢查 API 的基本結構，或僅部署和測試 API。

 PetStore 範例 API 支援下列方法，讓用戶端存取 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` 的 HTTP 後端網站。

**注意**  
本教學課程使用 HTTP 端點作為範例。當您建立自己的 API 時，我們建議您使用 HTTPS 端點進行 HTTP 整合。
+ `GET /`：適用於未與任何後端端點整合之 API 根資源的讀取存取。API Gateway 會回應 PetStore 網站的概觀。這是 `MOCK` 整合類型範例。
+ `GET /pets`：適用於與相同具名後端 `/pets` 資源整合之 API `/pets` 資源的讀取存取。後端會傳回 PetStore 中可用寵物的頁面。這是 `HTTP` 整合類型範例。整合端點的 URL 是 `http://petstore-demo-endpoint.execute-api.com/petstore/pets`。
+ `POST /pets`：適用於與後端 `/pets` 資源整合之 API `/petstore/pets` 資源的寫入存取。在收到正確的請求時，後端會將指定的寵物新增至 PetStore，並將結果傳回給發起人。此整合也是 `HTTP`。
+ `GET /pets/{petId}`：適用於指定為傳入請求 URL 之路徑變數的 `petId` 值所識別寵物的讀取存取。這個方法也有 `HTTP` 整合類型。後端會傳回 PetStore 中找到的指定寵物。後端 HTTP 端點的 URL 是 `http://petstore-demo-endpoint.execute-api.com/petstore/pets/n`，其中 `n` 是作為所查詢寵物識別符的整數。

 API 支援透過 `OPTIONS` 整合類型之 `MOCK` 方法的 CORS 存取。API Gateway 會傳回支援 CORS 存取的所需標頭。

下列程序會逐步解說如何使用 API Gateway 主控台從範例建立和測試 API。

**匯入、建置和測試範例 API**

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

1. 執行以下任意一項：
   + 若要建立您的第一個 API，請針對 **REST API** 選擇**建置**。
   + 如果您之前已建立 API，則選擇**建立 API**，然後針對 **REST API** 選擇**建置**。

1.  在**建立 REST API** 下，選擇**範例 API**，然後選擇**建立 API** 來建立範例 API。

      
![\[API Gateway 主控台的 REST API 範例。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-new-console.png)

    您可以先捲動 OpenAPI 定義以取得此範例 API 的詳細資訊，再選擇**建立 API**。

1. 在主導覽窗格中，選擇**資源**。新建立的 API 如下所示：

      
![\[匯入 API Gateway 主控台後的範例 API。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-result-new-console.png)

    **Resources (資源)** 窗格會將已建立 API 的結構顯示為節點樹狀結構。每個資源上所定義的 API 方法就是樹狀結構的邊緣。選取資源時，其所有方法都會列在右側的**方法**表中。每一種方法都會顯示方法類型、整合類型、授權類型和 API 金鑰需求。

1.  若要檢視方法的詳細資訊、修改其設定或測試方法呼叫，請從方法清單或資源樹狀結構中選擇方法名稱。在這裡，我們選擇 `POST /pets` 方法作為插圖：

      
![\[用於 API Gateway 主控台的範例 API 的 POST /pets 方法。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-post-method-execution-new-console.png)

    產生的**方法執行**窗格會顯示所選 (`POST /pets`) 方法結構和行為的邏輯檢視。

   **方法請求**和**方法回應**代表 API 與前端的介面，而**整合請求**和**整合回應**代表 API 與後端的介面。

    用戶端會使用 API 透過**方法請求**來存取後端功能。API Gateway 會在必要時先將用戶端請求轉譯為**整合請求**中後端可接受的形式，再將傳入請求轉送至後端。轉換後的請求稱為整合請求。同樣地，後端會傳回**整合回應**中的 API Gateway 回應。API Gateway 接著會先將它路由至 **Method Response (方法回應)**，再將它傳送至用戶端。同樣地，若有必要，API Gateway 可以將後端回應資料映射至用戶端所預期的形式。

    針對 API 資源上的 `POST` 方法，如果方法請求承載的格式與整合請求承載的格式相同，則可以將方法請求承載傳遞至整合請求，而不需要修改。

   `GET /` 方法請求會使用 `MOCK` 整合類型，而且未繫結至任何實際後端端點。對應的**整合回應**設定為傳回靜態 HTML 頁面。呼叫方法時，API Gateway 只需要接受請求，並立即透過**方法回應**，將已設定的整合回應傳回給用戶端。您可以使用模擬整合來測試 API，而不需要後端端點。您也可以使用它來服務從回應內文映射範本產生的本機回應。

   身為 API 開發人員，您可以設定方法請求和方法回應來控制 API 前端互動的行為。您可以設定整合請求和整合回應來控制 API 後端互動的行為。這些涉及方法與其映射整合之間的資料映射。現在，我們專注於測試 API，以提供端對端使用者體驗。

1.  選取**測試**索引標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1.  例如，若要測試 `POST /pets` 方法，請將下列 **\$1"type": "dog","price": 249.99\$1** 承載輸入至**請求內文**，然後選擇**測試**。

      
![\[在 API Gateway 主控台測試 POST 方法。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-post-method-test-new-console.png)

    輸入指定我們想要新增至 PetStore 網站上寵物清單的寵物屬性。

1. 結果顯示如下：

      
![\[在 API Gateway 主控台測試 POST 方法的結果。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-post-method-test-result-new-console.png)

    輸出的**日誌**項目會顯示從方法請求到整合請求，以及從整合回應到方法回應的狀態變更。這適用於故障診斷任何會導致請求失敗的映射錯誤問題。在這個範例中，不會套用任何映射：方法請求承載會透過整合請求傳遞至後端；且同樣地，後端回應會透過整合回應傳遞至方法回應。

    若要使用 API Gateway 測試呼叫請求功能以外的用戶端來測試 API，您必須先將 API 部署至階段。

1.  選擇**部署 API**以部署範例 API。

      
![\[使用部署按鈕來部署您的 API，讓 API 呼叫者可以調用您的 API。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-deploy-api-new-console.png)

1. 針對**階段**，選取**新增階段**，然後輸入 **test**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

1.  在產生的**階段**窗格中的**階段詳細資訊**下，**調用 URL** 會顯示調用 API 的 `GET /` 方法請求的 URL。  
![\[在建立 REST API 之後，主控台會顯示 API 的調用 URL。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/getting-started-rest-invoke-url.png)

1. 選擇複製圖示以複製您的 API 的調用 URL，然後在 Web 瀏覽器中輸入您的 API 調用 URL。成功回應會傳回整合回應中從映射範本產生的結果。

1.  在 **Stages** (階段) 導覽窗格中，展開 **test** (測試) 階段，並選取 `/pets/{petId}` 上的 **GET**，然後複製 `https://api-id.execute-api.region.amazonaws.com/test/pets/{petId}` 的 **Invoke URL** (叫用 URL) 值。`{petId}` 代表路徑變數。

    將 **Invoke URL (呼叫 URL)** 值 (在前一個步驟中取得) 貼入瀏覽器的網址列 (例如，將 `{petId}` 取代為 `1`)，以及按 Enter 來提交請求。200 OK 回應傳回時應該具有下列 JSON 承載：

   ```
   {
     "id": 1,
     "type": "dog",
     "price": 249.99
   }
   ```

    如所示呼叫 API 方法可能是因為其 **Authorization (授權)** 類型設定為 `NONE`。如果使用 `AWS_IAM` 授權，請使用[第 4 版簽署程序](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html) (SigV4) 或[第 4a 版簽署程序](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html#how-sigv4a-works) (SigV4a) 通訊協定來簽署請求。如需這類請求的範例，請參閱[教學：建立具有 HTTP 非代理整合的 REST API](api-gateway-create-api-step-by-step.md)。

# 選擇 HTTP 整合教學課程
<a name="getting-started-http-integrations"></a>

 若要建置具有 HTTP 整合的 API，您可以使用 HTTP 代理整合或 HTTP 自訂整合。

在 HTTP 代理整合中，您只需根據後端需求來設定 HTTP 方法和 HTTP 端點 URI。建議您盡可能使用 HTTP 代理整合，以充分善用簡化的 API 設定。

如果您需要為後端轉換用戶端請求資料，或為用戶端轉換後端回應資料，您可能會想要使用 HTTP 自訂整合。

**Topics**
+ [

# 教學：建立具有 HTTP 代理整合的 REST API
](api-gateway-create-api-as-simple-proxy-for-http.md)
+ [

# 教學：建立具有 HTTP 非代理整合的 REST API
](api-gateway-create-api-step-by-step.md)

# 教學：建立具有 HTTP 代理整合的 REST API
<a name="api-gateway-create-api-as-simple-proxy-for-http"></a>

HTTP 代理整合是建置 API 的簡單、功能強大且多樣化的機制，可讓 Web 應用程式存取整合式 HTTP 端點 (例如整個網站) 的多個資源或功能，以簡化單一 API 方法的設定。在 HTTP 代理整合中，API Gateway 會將用戶端提交的方法請求傳遞至後端。傳遞的請求資料包含請求標頭、查詢字串參數、URL 路徑變數和承載。後端 HTTP 端點或 Web 伺服器會剖析傳入請求資料，以判斷其所傳回的回應。在設定 API 方法之後，HTTP 代理整合可讓用戶端和後端直接互動，而不需要 API Gateway 介入，除了 [Amazon API Gateway 重要說明](api-gateway-known-issues.md)所列的一些已知問題，例如不支援的字元。

使用全能代理資源 `{proxy+}`，以及 HTTP 方法的 catch-all `ANY` 動詞，您可以使用 HTTP 代理整合來建立單一 API 方法的 API。此方法會公開網站的整個可公開存取的 HTTP 資源和操作集。後端 Web 伺服器開啟更多資源來進行公開存取時，用戶端可以搭配使用這些新的資源與相同的 API 設定。若要啟用此功能，網站開發人員必須與用戶端開發人員清楚地溝通新資源以及每個新資源適用的操作。



下列教學是快速簡介，可示範 HTTP 代理整合。在教學課程中，我們使用 API Gateway 主控台建立 API 以透過一般代理資源 `{proxy+}` 與 PetStore 網站整合，並建立 HTTP 方法預留位置 `ANY`。

**Topics**
+ [

## 使用 API Gateway 主控台來建立具有 HTTP 代理整合的 API。
](#api-gateway-create-api-as-simple-proxy-for-http-build)
+ [

## 測試具有 HTTP 代理整合的 API
](#api-gateway-create-api-as-simple-proxy-for-http-test)

## 使用 API Gateway 主控台來建立具有 HTTP 代理整合的 API。
<a name="api-gateway-create-api-as-simple-proxy-for-http-build"></a>

 下列程序會逐步解說如何使用 API Gateway 主控台，建立和測試具有 HTTP 後端之代理資源的 API。HTTP 後端是「`PetStore`」中的 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` 網站 ([教學：建立具有 HTTP 非代理整合的 REST API](api-gateway-create-api-step-by-step.md))；其中，螢幕擷取畫面是用來顯示提醒，以說明 API Gateway UI 元素。如果您是第一次使用 API Gateway 主控台來建立 API，則建議您先遵循該節。

**建立 API**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇**組建**。

1.  對於**API 名稱**，輸入 **HTTPProxyAPI**。

1. 在**描述**，請輸入描述。

1. 將 **API 端點類型**保持設定為**區域**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇**建立 API**。

在此步驟中，您會建立 `{proxy+}` 的代理資源路徑。這是 `http://petstore-demo-endpoint.execute-api.com/` 下方之任何後端端點的預留位置。例如，它可以是 `petstore`、`petstore/pets` 和 `petstore/pets/{petId}`。API Gateway 會在您建立 `{proxy+}` 資源時建立 `ANY` 方法，並在執行時間將該方法作為任何受支援 HTTP 動詞的預留位置。

**建立 **/\$1proxy\$1\$1** 資源**

1. 選擇您的 API。

1. 在主導覽窗格中，選擇**資源**。

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

1. 開啟**代理資源**。

1. 將**資源路徑**保持為 `/`。

1. 針對**資源名稱**，輸入 **\$1proxy\$1\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

1. 選擇**建立資源**。  
![\[建立子資源。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-simple-proxy-create-proxy-resource-new-console.png)

在此步驟中，您會使用代理整合將 `ANY` 方法與後端 HTTP 端點整合。在代理整合中，API Gateway 會將用戶端提交的方法請求傳遞至後端，而不需要 API Gateway 介入。

**建立 `ANY` 方法**

1. 選擇 **/\$1proxy\$1\$1** 資源。

1. 選擇 **ANY** 方法。

1. 在警告符號下，選擇**編輯整合**。如果 API 的方法沒有整合，便無法部署該 API。

1. 針對**整合類型**，選取 **HTTP**。

1. 開啟 **HTTP 代理整合**。

1. 針對 **HTTP 方法**，選取 **ANY**。

1. 針對**端點 URL**，輸入 **http://petstore-demo-endpoint.execute-api.com/\$1proxy\$1**。

1. 選擇**儲存**。

## 測試具有 HTTP 代理整合的 API
<a name="api-gateway-create-api-as-simple-proxy-for-http-test"></a>

 特定用戶端請求成功與否取決於下列項目：
+  如果後端已讓對應的後端端點可供使用，因此已授予所需的存取許可。
+ 如果用戶端提供正確的輸入。

例如，這裡使用的 PetStore API 未公開 `/petstore` 資源。因此，您會取得包含錯誤訊息 `404 Resource Not Found` 的 `Cannot GET /petstore` 回應。

此外，用戶端必須能夠處理後端的輸出格式，才能正確地剖析結果。API Gateway 不會居中來促進用戶端與後端之間的互動。

**透過代理資源使用 HTTP 代理整合來測試與 PetStore 網站整合的 API**

1. 選取**測試**索引標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

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

1. 針對**路徑**，在**代理**下輸入 **petstore/pets**。

1. 針對**查詢字串**，輸入 **type=fish**。

1. 選擇**測試**。

     
![\[使用測試功能來測試方法。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-simple-proxy-petstore-call-proxy-resource-new-console.png)

   因為後端網站支援 `GET /petstore/pets?type=fish` 請求，所以它會傳回與下列類似的成功回應：

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

   如果您嘗試呼叫 `GET /petstore`，則會取得具有錯誤訊息 `404` 的 `Cannot GET /petstore` 回應。原因是後端不支援指定的操作。如果您呼叫 `GET /petstore/pets/1`，則會取得具有下列承載的 `200 OK` 回應，因為 PetStore 網站支援請求。

   ```
   {
     "id": 1,
     "type": "dog",
     "price": 249.99
   }
   ```

您也可以使用瀏覽器來測試您的 API。部署您的 API 並將其關聯到某個階段，以建立 API 的調用 URL。

**部署 API**

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **test**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

現在，用戶端可以呼叫您的 API。

**若要調用您的 API**

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

1. 選擇您的 API。

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

1. 在**階段詳細資訊**下，選擇複製圖示以複製 API 的調用 URL。

   在 Web 瀏覽器中輸入 API 的調用 URL。

   完整 URL 看起來應該會像這樣：`https://abcdef123.execute-api.us-east-2.amazonaws.com/test/petstore/pets?type=fish`。

   您的瀏覽器將向 API 傳送 `GET` 請求。

1. 結果應該與在 API Gateway 主控台中使用**測試**時所傳回的結果相同。

# 教學：建立具有 HTTP 非代理整合的 REST API
<a name="api-gateway-create-api-step-by-step"></a>

 在本教學課程中，您會使用 Amazon API Gateway 主控台從頭開始建立 API。您可以將主控台視為 API 設計工作室，並使用它來限定 API 功能範圍、測試其行為、建立 API，以及分階段部署您的 API。

**Topics**
+ [

## 建立具有 HTTP 自訂整合的 API
](#api-gateway-create-resource-and-methods)
+ [

## (選用) 映射請求參數
](#api-gateway-create-resources-and-methods-next-steps)

## 建立具有 HTTP 自訂整合的 API
<a name="api-gateway-create-resource-and-methods"></a>

 本節將逐步引導您建立資源、在資源上公開方法、設定方法來達到所需的 API 行為，以及測試與部署 API。

在此步驟中，您將建立空白 API。在以下步驟中，您會建立資源和方法，以使用非代理 HTTP 整合將 API 連線到 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` 端點。

**建立 API**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇**組建**。

1.  對於**API 名稱**，輸入 **HTTPNonProxyAPI**。

1. 在**描述**，請輸入描述。

1. 將 **API 端點類型**保持設定為**區域**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇**建立 API**。

**Resources (資源)** 樹狀目錄顯示不含任何方法的根資源 (`/`)。在此練習中，我們將建立具有 PetStore 網站 (http://petstore-demo-endpoint.execute-api.com/petstore/pets) 之 HTTP 自訂整合的 API 為了方便說明，我們將建立 `/pets` 資源作為根目錄的子目錄，並在此資源上公開 GET 方法，讓用戶端可以從 PetStore 網站擷取可用的 Pets (寵物) 項目清單。

**建立 /pets 資源**

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

1. 讓**代理資源**保持關閉。

1. 將**資源路徑**保持為 `/`。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

在此步驟中，您會在 **/pets** 資源上建立 `GET` 方法。`GET` 方法會與 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` 網站整合。API 方法的其他選項包括以下項目：
+ **POST**，主要用來建立子資源。
+ **PUT**，主要用來更新現有的資源 (也可用來建立子資源，但不建議)。
+ **DELETE**，用來刪除資源。
+ **PATCH**，用來更新資源。
+ **HEAD**，主要用來測試案例。它與 GET 相同，但不會傳回資源顯示方式。
+ **OPTIONS**，發起人可以使用它來取得目標服務之可用通訊選項的相關資訊。

 對於整合請求的 **HTTP method (HTTP 方法)**，您必須選擇後端支援的方法。對於 `HTTP` 或 `Mock integration`，方法請求與整合請求最好使用相同的 HTTP 動詞。對於其他整合類型，方法請求可能會使用與整合請求不同的 HTTP 動詞。例如，若要呼叫 Lambda 函數，整合請求必須使用 `POST` 來叫用函數，而方法請求則可根據 Lambda 函數的邏輯來使用任何 HTTP 動詞。

**在 **/pets** 資源上建立 `GET` 方法**

1. 選取 **/pets** 資源。

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

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

1. 針對**整合類型**，選取 **HTTP 整合**。

1. 讓 **HTTP 代理整合**保持關閉。

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

1. 針對**端點 URL**，輸入 **http://petstore-demo-endpoint.execute-api.com/petstore/pets**。

   PetStore 網站可讓您依指定頁面上的寵物類型 (例如 "Dog" 或 "Cat") 擷取 `Pet` 項目清單。

1. 針對**內容處理**，選取**傳遞**。

1. 選擇 **URL 查詢字串參數**。

   PetStore 網站使用 `type` 與 `page` 查詢字串參數來接受輸入內容。您會將查詢字串參數新增至方法請求，然後將其映射至整合請求的映射查詢字串。

1. 若要將查詢字串參數，請執行下列操作：

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

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

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

   重複上述步驟，另外建立名稱為 **page** 的查詢字串。

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

用戶端現在可以在提交請求時，提供寵物類型與頁碼作為查詢字串參數。這些輸入參數必須映射到整合的查詢字串參數，以將輸入值轉送至後端的 PetStore 網站。

**將輸入參數映射至整合請求**

1. 在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

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

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

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

   1. 對於**映射自**，輸入 **method.request.querystring.type**。

   1. 讓**快取**保持關閉。

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

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

   1. 對於**映射自**，輸入 **method.request.querystring.page**。

   1. 讓**快取**保持關閉。

1. 選擇**儲存**。

**若要測試 API**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 針對**查詢字串**，輸入 **type=Dog&page=2**。

1. 選擇**測試**。

    結果類似如下：

      
![\[測試呼叫 GET on Pets 方法結果\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-create-api-step-by-step-test-invoke-get-on-pets-result-new-console.png)

    現在測試成功，我們可以部署 API 來公開提供使用。

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **Prod**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

1.  (選用) 針對**階段詳細資訊**下的**調用 URL**，您可以選擇複製圖示以複製 API 的調用 URL。您可以使用此項與 [Postman](https://www.postman.com) 和 [cURL](https://curl.se/) 這類工具搭配，來測試您的 API。

 如果您使用開發套件建立用戶端，您可以呼叫開發套件所公開的方法來簽署請求。如需實作詳細資訊，請參閱您選擇的 [AWS 軟體開發套件](https://aws.amazon.com/developer/tools/)。

**注意**  
 當您的 API 變更時，您必須重新部署 API，以提供新的或更新的功能，再重新呼叫請求 URL。

## (選用) 映射請求參數
<a name="api-gateway-create-resources-and-methods-next-steps"></a>

### 對應 API Gateway API 的請求參數
<a name="getting-started-mappings"></a>

 本教學課程顯示如何在 API 的方法請求上建立 `{petId}` 的路徑參數，以指定項目 ID、將它映射至整合請求 URL 中的 `{id}` 路徑參數，然後將請求傳送到 HTTP 端點。

**注意**  
 如果您輸入大小寫錯誤的字母 (例如輸入小寫字母而非大寫字母)，這可能會在稍後的演練中造成錯誤。

#### 步驟 1：建立資源
<a name="getting-started-mappings-add-resources"></a>

在此步驟中，您會建立路徑參數為 \$1petId\$1 的資源。

**建立 \$1petId\$1 資源**

1. 選取 **/pets** 資源，然後選擇**建立資源**。

1. 讓**代理資源**保持關閉。

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

1. 針對**資源名稱**，輸入 **\$1petId\$1**。

    使用大括號 (`{ }`) 括住 `petId`，以便顯示 **/pets/\$1petId\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

#### 步驟 2：建立及測試方法
<a name="getting-started-mappings-set-methods"></a>

 在此步驟中，您會建立路徑參數為 `{petId}` 的 `GET` 方法。

**設定 GET 方法**

1. 選取 **/\$1petId\$1** 資源，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **HTTP 整合**。

1. 讓 **HTTP 代理整合**保持關閉。

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

1. 針對**端點 URL**，輸入 **http://petstore-demo-endpoint.execute-api.com/petstore/pets/\$1id\$1**。

1. 針對**內容處理**，選取**傳遞**。

1. 讓**預設逾時**保持開啟。

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

此時您將剛建立的 `{petId}` 路徑參數映射至整合請求之 HTTP 端點 URL 中的 `{id}` 路徑參數。HTTP 端點 URL 為 **http://petstore-demo-endpoint.execute-api.com/petstore/pets/\$1id\$1**。

**映射 `{petId}` 路徑參數**

1. 在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

1. 選擇 **URL 路徑參數**。

1.  API Gateway 會為名為 **petId** 的整合請求建立路徑參數，但此路徑參數對於您設定為後端整合的 HTTP 端點 URL 無效。HTTP 端點會使用 `{id}` 作為路徑參數。針對**名稱**，刪除 **petId** 並輸入 **id**。

   這會將 `petId` 的方法請求路徑參數對應到 `id` 的整合請求路徑參數。

1. 選擇**儲存**。

現在，請測試該方法。

**測試該方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 在 **petId** 的**路徑**下，輸入 **4**。

1. 選擇**測試**。

   若成功，**回應內文**會顯示如下：

   ```
   {
     "id": 4,
     "type": "bird",
     "price": 999.99
   }
   ```

#### 步驟 3：部署 API
<a name="getting-started-mappings-deploy"></a>

在此步驟中，將會部署 API，如此您即開始從 API Gateway 主控台之外呼叫 API。

**部署 API**

1. 選擇**部署 API**。

1. 對於**階段**，選取**生產**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

#### 步驟 4：測試 API
<a name="getting-started-mappings-test"></a>

在此步驟中，您會在 API Gateway 主控台外使用您的 API 存取 HTTP 端點。

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

1. 在**階段詳細資訊**下，選擇複製圖示以複製 API 的調用 URL。

   此 URL 看起來如下：

   ```
   https://my-api-id.execute-api.region-id.amazonaws.com/prod
   ```

1. 在新瀏覽器標籤的地址方塊中輸入此 URL，並為此 URL 附加 `/pets/4`，然後才提交請求。

1. 瀏覽器會傳回以下內容：

   ```
   {
     "id": 4,
     "type": "bird",
     "price": 999.99
   }
   ```

#### 後續步驟
<a name="api-gateway-create-resources-and-methods-next-steps"></a>

您可以開啟請求驗證、轉換資料或建立自訂閘道回應，以進一步自訂 API。

若要探索更多自訂 API 的方法，請參閱下列教學課程：
+ 如需請求驗證的詳細資訊，請參閱「[在 API Gateway 中設定基本請求驗證](api-gateway-request-validation-set-up.md)」。
+ 如需如何轉換請求和回應承載的相關資訊，請參閱[教學課程：修改 AWS 服務整合的整合請求和回應](set-up-data-transformations-in-api-gateway.md)。
+ 如需如何建立自訂閘道回應的相關資訊，請參閱[使用 API Gateway 主控台設定 REST API 的閘道回應](set-up-gateway-response-using-the-console.md)。

# 教學：建立具私有整合的 REST API
<a name="getting-started-with-private-integration"></a>

在本教學課程中，您會建立 REST API，連線至在 Amazon VPC 中執行的 Amazon ECS 服務。不在您 Amazon VPC 上的客戶可以使用該 API 來存取您的 Amazon ECS 服務。

此教學課程需約 1 小時方能完成。首先，您使用 CloudFormation 範本來建立 Amazon VPC 和 Amazon ECS 服務。然後，您可以使用 API Gateway 主控台來建立 VPC 連結 V2。VPC 連結允許 API Gateway 存取在您 Amazon VPC 中執行的 Amazon ECS 服務。接著，您建立使用 VPC 連結 V2 連線至 Amazon ECS 服務的 REST API。最後，測試您的 API。

當您叫用 REST API 時，API Gateway 會透過 VPC 連結 V2 將請求路由到您的 Amazon ECS 服務，然後從服務傳回回應。

**注意**  
此教學課程先前支援 HTTP APIs，現在支援使用 VPC 連結 V2 APIs。

![\[在本教學課程中建立 REST API 的概觀。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/private-integration-rest.png)


若要完成本教學課程，您需要 AWS 帳戶和具有主控台存取權 AWS Identity and Access Management 的使用者。如需詳細資訊，請參閱[設定為使用 API Gateway](setting-up.md)。

**Topics**
+ [

## 步驟 1：建立 Amazon ECS 服務
](#rest-api-private-integration-create-ecs-service)
+ [

## 步驟 2：建立 VPC 連結
](#http-api-private-integration-vpc-link)
+ [

## 步驟 3：建立 REST API
](#http-api-private-integration-create-api)
+ [

## 步驟 4：測試您的 API
](#rest-api-private-integration-test-api)
+ [

## 步驟 5：部署 API
](#rest-api-private-integration-deploy-api)
+ [

## 步驟 6：呼叫您的 API
](#rest-api-private-integration-call)
+ [

## 步驟 7：清除
](#rest-api-private-integration-cleanup)

## 步驟 1：建立 Amazon ECS 服務
<a name="rest-api-private-integration-create-ecs-service"></a>

Amazon ECS 是一種容器管理服務，可以在叢集上輕鬆執行、停止及管理 Docker 容器。在本教學課程中，您可以在 Amazon ECS 管理的無伺服器基礎設施上執行叢集。

下載並解壓縮[此 CloudFormation 範本](samples/rest-private-integration-tutorial.zip)，這會建立服務的所有相依性，包括 Amazon VPC。您可以使用範本來建立使用 Application Load Balancer 的 Amazon ECS 服務。

**建立 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 (堆疊名稱)**，輸入 **rest-api-private-integrations-tutorial**，然後選擇 **Next (下一步)**。

1. 針對 **Configure stack options (設定堆疊選項)**，選擇 **Next (下一步)**。

1. 針對 **功能**，確認 CloudFormation 可以在您的帳戶中建立 IAM 資源。

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

CloudFormation 會佈建 ECS 服務，這可能需要幾分鐘的時間。當 CloudFormation 堆疊的狀態為 **CREATE\$1COMPLETE** 時，您就可以繼續進行下一個步驟。

## 步驟 2：建立 VPC 連結
<a name="http-api-private-integration-vpc-link"></a>

VPC 連結允許 API Gateway 存取 Amazon VPC 中的私有資源。您可以使用 VPC 連結，允許用戶端透過 REST API 存取您的 Amazon ECS 服務。

**建立 VPC 連結**

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

1. 在主要導覽窗格中，選擇 **VPC 連結**，然後選擇**建立**。

   您可能需要選擇選單圖示，才能開啟主要導覽窗格。

1. 針對**選擇 VPC 連結版本**，選取 **VPC 連結 V2**。

1. 針對 **Name** (名稱)，輸入 **private-integrations-tutorial**。

1. 在 **VPC** 欄位選擇您在步驟 1 建立的 VPC。名稱應以 **RestApiStack** 開頭。

1. 對於 **Subnets** (子網路)，請在您的 VPC 中選取兩個私有子網路。它們的名稱要以 `PrivateSubnet` 結尾。

1. 對於**安全群組**，選取以 `private-integrations-tutorial` 開頭且描述為 `RestApiStack/RestApiTutorialService/Service/SecurityGroup` 的群組 ID。

1. 選擇**建立**。

建立 VPC 連結 V2 之後，API Gateway 會佈建彈性網路界面來存取 VPC。該程序需要幾分鐘的時間。同時，您可以創建您的 API。

## 步驟 3：建立 REST API
<a name="http-api-private-integration-create-api"></a>

REST API 為您的 Amazon ECS 服務提供 HTTP 端點。



**若要建立 REST API**

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

1. 選擇 **Create API (建立 API)**，然後針對 **REST API**，選擇 **Build (建置)**。

1. 對於**名稱**，輸入 **private-integration-api**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇**建立 API**。

   建立 API 之後，您可以建立 方法。

1. 選擇**建立方法**，然後執行下列動作：

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

   1. 針對**整合類型**，選取 **VPC 連結**。

   1. 開啟 **VPC 代理整合**。

   1. 針對 **HTTP 方法**，選取 `GET`。

   1. 針對 **VPC 連結**，選擇您在上一個步驟中建立的 VPC 連結 V2。

   1. 針對**整合目標**，輸入您在步驟 1 中使用範本建立的 CloudFormation 負載平衡器。其名稱應以 **rest-** 開頭。

   1. 針對**端點 URL**，輸入 `http://private-integrations-tutorial.com`。

      URL 用於設定整合請求的`Host`標頭。在此情況下，主機標頭為 **private-integrations-tutorial**。

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

      透過代理整合，API 已準備好進行測試。

## 步驟 4：測試您的 API
<a name="rest-api-private-integration-test-api"></a>

接著，您會測試叫用 API 方法。

**測試您的 API**

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

1. 選擇您的 API。

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 選擇**測試**

   確認 API 的回應是一則歡迎訊息，告知您應用程式正在 Amazon ECS 上執行。

## 步驟 5：部署 API
<a name="rest-api-private-integration-deploy-api"></a>

接著，部署您的 API。

**部署 API**

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **Prod**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

## 步驟 6：呼叫您的 API
<a name="rest-api-private-integration-call"></a>

部署 API 之後，您可以呼叫它。

**呼叫您的 API**

1. 在 Web 瀏覽器中輸入調用 URL。

   完整 URL 看起來應該會像這樣：`https://abcd123.execute-api.us-east-2.amazonaws.com/Prod`。

   您的瀏覽器將向 API 傳送 `GET` 請求。

1. 確認 API 的回應是一則歡迎訊息，告知您應用程式正在 Amazon ECS 上執行。

   如果您看到歡迎訊息，表示您已成功建立在 Amazon VPC 中執行的 Amazon ECS 服務，並使用 API Gateway REST API 搭配 VPC 連結 V2 來存取 Amazon ECS 服務。

## 步驟 7：清除
<a name="rest-api-private-integration-cleanup"></a>

若要避免不必要的成本，請刪除您在此教學課程中建立的資源。下列步驟會刪除您的 VPC 連結 V2、 CloudFormation stack 和 REST API。

**刪除 REST API**

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

1. 在 **API** 頁面上，選取 API。依次選擇 **Actions** (動作)、**Delete** (刪除)，然後確認您的選擇。

**刪除 VPC 連結**

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

1. 選擇 **VPC link** (VPC 連結)。

1. 選取您的 VPC 連結、選擇 **Delete** (刪除)，然後確認您的選擇。

**刪除 CloudFormation 堆疊**

1. 在 https：//[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 開啟 CloudFormation 主控台。

1. 選取您的 CloudFormation 堆疊。

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

# 教學課程：使用 AWS 整合建立 REST API
<a name="getting-started-aws-proxy"></a>

 如需了解如何建立 API Gateway API 以公開整合的 Lambda 函數，請參閱[教學：建立具 Lambda 代理整合的 REST API](api-gateway-create-api-as-simple-proxy-for-lambda.md) 和[教學：建立具 Lambda 非代理整合的 REST API](getting-started-lambda-non-proxy-integration.md) 主題。此外，您可以建立 API Gateway API 來公開其他服務 AWS ，例如 Amazon SNS、Amazon S3、Amazon Kinesis 甚至 AWS Lambda。這可透過 `AWS` 整合進行。Lambda 整合或 Lambda 代理整合則屬於特殊案例，這些項目會透過 API Gateway API 來公開叫用 Lambda 函數。

 所有 AWS 服務都支援專用 APIs來公開其功能。不過，應用程式協定或程式設計界面可能會因服務而不同。具有 `AWS`整合的 API Gateway API 可為您的用戶端提供一致的應用程式通訊協定，以存取不同的 AWS 服務。

 在本演練中，我們會建立 API 來公開 Amazon SNS。如需將 API 與其他 AWS 服務整合的更多範例，請參閱 [Amazon API Gateway 教學課程和研討會](api-gateway-tutorials.md)。

 與 Lambda 代理整合不同，其他 AWS 服務沒有對應的代理整合。因此，API 方法與單一 AWS 動作整合。如需更多的彈性，您可以設定 Lambda 代理整合，這種方法與代理整合類似。Lambda 函數接著會剖析和處理其他 AWS 動作的請求。

 如果端點逾時，則 API Gateway 不會重試，API 發起人必須實作重試邏輯來處理端點逾時。

 此演練採用 [教學：建立具 Lambda 非代理整合的 REST API](getting-started-lambda-non-proxy-integration.md) 中的說明與概念為基礎。若您尚未完成該演練，建議先行完成。



**Topics**
+ [

## 先決條件
](#getting-started-aws-proxy-prerequisites)
+ [

## 步驟 1：建立 AWS 服務代理執行角色
](#getting-started-aws-proxy-add-roles)
+ [

## 步驟 2：建立資源
](#getting-started-aws-proxy-add-resources)
+ [

## 步驟 3：建立 GET 方法
](#getting-started-aws-proxy-add-methods)
+ [

## 步驟 4：指定方法設定並測試方法
](#getting-started-aws-proxy-set-methods)
+ [

## 步驟 5：部署 API
](#getting-started-aws-proxy-deploy)
+ [

## 步驟 6：測試 API
](#getting-started-aws-proxy-test)
+ [

## 步驟 7：清除
](#getting-started-aws-proxy-clean-up)

## 先決條件
<a name="getting-started-aws-proxy-prerequisites"></a>

開始此演練前，請執行下列操作：

1. 完成「[設定為使用 API Gateway](setting-up.md)」中的步驟。

1.  建立名為 `MyDemoAPI` 的新 API。如需詳細資訊，請參閱 [教學：建立具有 HTTP 非代理整合的 REST API](api-gateway-create-api-step-by-step.md)。

1. 至少將 API 部署至名為 `test` 的階段一次。如需詳細資訊，請參閱「[」中的「](getting-started-lambda-non-proxy-integration.md#getting-started-deploy-api)部署 API[選擇 AWS Lambda 整合教學課程](getting-started-with-lambda-integration.md)」。

1. 完成 中的其餘步驟[選擇 AWS Lambda 整合教學課程](getting-started-with-lambda-integration.md)

1. 在 Amazon Simple Notification Service (Amazon SNS) 中建立至少一個主題。您將使用部署的 API 來取得與您 AWS 帳戶相關聯的 Amazon SNS 主題清單。如需了解如何在 Amazon SNS 中建立主題，請參閱[建立主題](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html)。(您不需要複製步驟 5 中提到的主題 ARN。)

## 步驟 1：建立 AWS 服務代理執行角色
<a name="getting-started-aws-proxy-add-roles"></a>

 若要允許 API 調用 Amazon SNS 動作，您必須將適當的 IAM 政策附加至 IAM 角色。在此步驟中，您會建立新的 IAM 角色。

**建立 AWS 服務代理執行角色**

1. 登入 AWS 管理主控台 ，並在 https：//[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 開啟 IAM 主控台。

1. 選擇**角色**。

1. 選擇建**立角色**。

1.  在**選取信任的實體類型**下選擇 **AWS 服務**，然後選取 **API Gateway** 並選取**允許 API Gateway 將日誌推送到 CloudWatch Logs**。

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

1. 針對**角色名稱**，輸入 **APIGatewaySNSProxyPolicy**，然後選擇**建立角色**。

1. 在**角色**清單中，選擇您剛剛建立的角色。您可能需要捲動或使用搜尋列來尋找該角色。

1. 針對選取的角色，選取 **許可** 索引標籤。

1. 在下拉式清單中，選擇 **連接政策**。

1. 在搜尋列中輸入 **AmazonSNSReadOnlyAccess**，並選擇**新增許可**。
**注意**  
本教學課程為了簡單起見，使用受管理政策。最佳實務是，您應建立自己的 IAM 政策以授予所需的最低許可。

1. 記下新建的**角色 ARN**，以在稍後使用。

## 步驟 2：建立資源
<a name="getting-started-aws-proxy-add-resources"></a>

在此步驟中，您會建立資源，讓 AWS 服務代理能夠與服務互動 AWS 。

**建立資源**

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

1. 選擇您的 API。

1. 選取根資源 **/** (其以一條正斜線 (**/**) 表示)，然後選擇**建立資源**。

1. 讓**代理資源**保持關閉。

1. 將**資源路徑**保持為 `/`。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

## 步驟 3：建立 GET 方法
<a name="getting-started-aws-proxy-add-methods"></a>

在此步驟中，您會建立 GET 方法，讓 AWS 服務代理能夠與服務互動 AWS 。

**建立 `GET` 方法**

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Amazon SNS 主題 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Amazon SNS**。

1. 讓 **AWS 子網域**保持空白。

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

1. 針對**動作類型**，選取**使用動作名稱**。

1. 針對**動作名稱**，輸入 **ListTopics**。

1. 針對**執行角色**，輸入 **APIGatewaySNSProxyPolicy** 的角色 ARN。

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

## 步驟 4：指定方法設定並測試方法
<a name="getting-started-aws-proxy-set-methods"></a>

您現在可以測試您的 `GET` 方法，確認其已正確設定，可以列出您的 Amazon SNS 主題。

**測試 `GET` 方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 選擇**測試**。

   結果會顯示類似以下內容的回應：

   ```
   {
     "ListTopicsResponse": {
       "ListTopicsResult": {
         "NextToken": null,
         "Topics": [
           {
             "TopicArn": "arn:aws:sns:us-east-1:80398EXAMPLE:MySNSTopic-1"
           },
           {
             "TopicArn": "arn:aws:sns:us-east-1:80398EXAMPLE:MySNSTopic-2"
           },
           ...
           {
             "TopicArn": "arn:aws:sns:us-east-1:80398EXAMPLE:MySNSTopic-N"
           }
         ]
       },
       "ResponseMetadata": {
         "RequestId": "abc1de23-45fa-6789-b0c1-d2e345fa6b78"
       }
     }
   }
   ```

## 步驟 5：部署 API
<a name="getting-started-aws-proxy-deploy"></a>

在此步驟中，您將部署 API 以從 API Gateway 主控台外部呼叫 API。

**部署 API**

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **test**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

## 步驟 6：測試 API
<a name="getting-started-aws-proxy-test"></a>

在此步驟中，您會離開 API Gateway 主控台，並使用 AWS 服務代理與 Amazon SNS 服務互動。

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

1. 在**階段詳細資訊**下，選擇複製圖示以複製 API 的調用 URL。

   它應該如下所示：

   ```
   https://my-api-id.execute-api.region-id.amazonaws.com/test
   ```

1. 將 URL 輸入到新瀏覽器標籤的網址方塊中。

1. 附加 `/mydemoawsproxy`，讓 URL 看起來如下：

   ```
   https://my-api-id.execute-api.region-id.amazonaws.com/test/mydemoawsproxy
   ```

   瀏覽至該 URL。應該會顯示類似如下的資訊：

   ```
   {"ListTopicsResponse":{"ListTopicsResult":{"NextToken": null,"Topics":[{"TopicArn": "arn:aws:sns:us-east-1:80398EXAMPLE:MySNSTopic-1"},{"TopicArn": "arn:aws:sns:us-east-1:80398EXAMPLE:MySNSTopic-2"},...{"TopicArn": "arn:aws:sns:us-east-1:80398EXAMPLE:MySNSTopic-N}]},"ResponseMetadata":{"RequestId":"abc1de23-45fa-6789-b0c1-d2e345fa6b78}}}
   ```

## 步驟 7：清除
<a name="getting-started-aws-proxy-clean-up"></a>

您可以刪除 AWS 服務代理需要運作的 IAM 資源。

**警告**  
如果您刪除 AWS 服務代理依賴的 IAM 資源，則該 AWS 服務代理及其依賴的任何 APIs 將無法再運作。IAM 資源一經刪除，即無法復原。如果您要再次使用該 IAM 資源，就必須予以重建。

**刪除相關聯的 IAM 資源**

1. 在以下網址開啟 IAM 主控台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 在 **Details (詳細資訊)** 區域中，選擇 **Roles (角色)**。

1. 選取 **APIGatewayAWSProxyExecRole**，然後依序選擇 **Role Actions (角色動作)** 和 **Delete Role (刪除角色)**。出現提示時，選擇 **Yes, Delete (是，刪除)**。

1. 在 **Details (詳細資訊)** 區域中，選擇 **Policies (政策)**。

1. 選取 **APIGatewayAWSProxyExecPolicy**，然後依序選擇 **Policy Actions (政策動作)** 和 **Delete (刪除)**。出現提示時，選擇 **Delete** (刪除)。

 本演練到此結束。如需建立 API 做為 AWS 服務代理的更詳細討論，請參閱 [教學：建立 REST API 做為 Amazon S3 代理](integrating-api-with-aws-services-s3.md)、 [教學課程：建立具有兩個 AWS 服務整合和一個 Lambda 非代理整合的計算器 REST API](integrating-api-with-aws-services-lambda.md)或 [教學課程：建立 REST API 做為 Amazon Kinesis 代理](integrating-api-with-aws-services-kinesis.md)。

# 教學課程：建立具有兩個 AWS 服務整合和一個 Lambda 非代理整合的計算器 REST API
<a name="integrating-api-with-aws-services-lambda"></a>

[教學：建立具 Lambda 非代理整合的 REST API](getting-started-lambda-non-proxy-integration.md) 僅使用 `Lambda Function` 整合。`Lambda Function` 整合是 `AWS Service` 整合類型的特殊案例，此整合類型會為您執行許多整合設定，例如自動新增調用 Lambda 函數所需的資源型許可權。在這裡，三種整合中的兩種會使用 `AWS Service` 整合。在此整合類型中，您具有更多的控制，但需要手動執行任務，像是建立和指定 IAM 角色，其中包含適當的許可。



在本教學課程中，您將需要建立 `Calc` Lambda 函數來實作基本算術運算，並接受和傳回 JSON 格式的輸入和輸出。然後，您將建立一個 REST API，並使用下列方式將其與 Lambda 函數整合：

1. 在 `GET` 資源上公開 `/calc` 方法來叫用 Lambda 函數，並提供輸入做為查詢字串參數。(`AWS Service` 整合)

1. 在 `POST` 資源上公開 `/calc` 方法來叫用 Lambda 函數，並在方法請求酬載中提供輸入。(`AWS Service` 整合)

1. 在巢狀 `GET` 資源上公開 `/calc/{operand1}/{operand2}/{operator}` 來叫用 Lambda 函數，並提供輸入做為路徑參數 (`Lambda Function` 整合)

除了試做本教學課程之外，您可能還想要研究 `Calc` API 的 [OpenAPI 定義檔](api-as-lambda-proxy-export-swagger-with-extensions.md)，您可以依照 [在 API Gateway 中使用 OpenAPI 開發 REST API](api-gateway-import-api.md) 中的指示，將此定義檔匯入至 API Gateway。

**Topics**
+ [

## 建立可擔任的 IAM 角色
](#api-as-lambda-proxy-setup-iam-role-policies)
+ [

## 建立 `Calc` Lambda 函數
](#api-as-lambda-proxy-create-lambda-function)
+ [

## 測試 `Calc` Lambda 函式
](#api-as-lambda-proxy-test-lambda-function-)
+ [

## 建立 `Calc` API
](#api-as-lambda-proxy-create-api-resources)
+ [

## 整合 1：建立 `GET` 方法與查詢參數搭配來呼叫 Lambda 函數
](#api-as-lambda-proxy-expose-get-method-with-query-strings-to-call-lambda-function)
+ [

## 整合 2：建立 `POST` 方法與 JSON 承載搭配來呼叫 Lambda 函數
](#api-as-lambda-proxy-expose-post-method-with-json-body-to-call-lambda-function)
+ [

## 整合 3：建立 `GET` 方法與路徑參數搭配來呼叫 Lambda 函數
](#api-as-lambda-proxy-expose-get-method-with-path-parameters-to-call-lambda-function)
+ [

# 與 Lambda 函數整合之範例 API 的 OpenAPI 定義
](api-as-lambda-proxy-export-swagger-with-extensions.md)

## 建立可擔任的 IAM 角色
<a name="api-as-lambda-proxy-setup-iam-role-policies"></a>

為了讓 API 叫用 `Calc` Lambda 函數，您將需要具有 API Gateway 可擔任的 IAM 角色，這是具有以下信任關係的 IAM 角色：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

您建立的角色將需要具有 Lambda [InvokeFunction](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html) 許可。否則，API 發起人將會收到 `500 Internal Server Error` 回應。若要將此許可給與角色，請將下列 IAM 政策連接至其中：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "*"
        }
    ]
}
```

------

以下是如何完成此全部操作的方式：

**建立 API Gateway 可擔任的 IAM 角色**

1. 登入 IAM 主控台。

1. 選擇**角色**。

1. 選擇 **Create Role (建立角色)**。

1. 在**選取可信任執行個體類型**下，選取 **AWS 服務**。

1. 在 **Choose the service that will use this role (選擇將使用此角色的服務)** 下，選擇 **Lambda (Lambda)**。

1. 選擇 **Next: Permissions (下一步：許可)**。

1. 選擇 **Create Policy (建立政策)**。

   **Create Policy (建立政策)** 主控台將開啟新的時段。在該視窗中，執行下列作業：

   1. 在 **JSON** 標籤中，用以下政策取代現有政策。

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "lambda:InvokeFunction",
                  "Resource": "*"
              }
          ]
      }
      ```

------

   1. 選擇 **Review policy (檢閱政策)**。

   1. 在 **Review Policy (檢閱政策)** 下，執行下列操作：

      1. 在 **Name (名稱)** 中輸入名稱，例如 **lambda\$1execute**。

      1. 選擇 **Create Policy (建立政策)**。

1. 在原本的 **Create Role (建立角色)** 主控台視窗中，執行下列動作：

   1. 在 **Attach permissions policies (連接許可政策)** 下方，從下拉式清單中選擇您的 **lambda\$1execute** 政策。

      如果您在清單中沒有看到您的政策，請選擇清單頂端的重新整理按鈕。(請不要重新整理瀏覽器頁面！)

   1. 選擇 **Next: Add Tags (下一步：新增標籤)**。

   1. 選擇 **Next:Review (下一步：檢閱)**。

   1. 在 **Role name (角色名稱)** 中輸入名稱，例如 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role**。

   1. 選擇 **Create Role** (建立角色)。

1. 從角色清單中選擇您的 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role**。

1. 選擇 **Trust Relationships (信任關係)** 標籤。

1. 選擇 **Edit trust relationship (編輯信任關係)**。

1. 用以下內容取代現有政策：

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Sid": "",
         "Effect": "Allow",
         "Principal": {
           "Service": [
             "lambda.amazonaws.com",
             "apigateway.amazonaws.com"
           ]
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

------

1. 選擇 **Update Trust Policy (更新信任政策)**。

1. 請記住您剛建立角色的角色 ARN。以供稍後使用。

## 建立 `Calc` Lambda 函數
<a name="api-as-lambda-proxy-create-lambda-function"></a>

接下來，您會使用 Lambda 主控台建立 Lambda 函數。

1. 在 Lambda 主控台中，請選擇 **Create function (建立函數)**。

1. 選擇 **Author from Scratch (從頭開始撰寫)**。

1. 針對**名稱**，輸入 **Calc**。

1. 針對**執行期**，請選擇最新支援的 **Node.js** 或 **Python** 執行期。

1. 其他所有選項請使用預設設定。

1. 選擇**建立函數**。

1.  在 Lambda 主控台中，複製下列 Lambda 函數，並將其貼入程式碼編輯器。

------
#### [ Node.js ]

   ```
   export const handler = async function (event, context) {
     console.log("Received event:", JSON.stringify(event));
   
     if (
       event.a === undefined ||
       event.b === undefined ||
       event.op === undefined
     ) {
       return "400 Invalid Input";
     }
   
     const res = {};
     res.a = Number(event.a);
     res.b = Number(event.b);
     res.op = event.op;
     if (isNaN(event.a) || isNaN(event.b)) {
       return "400 Invalid Operand";
     }
     switch (event.op) {
       case "+":
       case "add":
         res.c = res.a + res.b;
         break;
       case "-":
       case "sub":
         res.c = res.a - res.b;
         break;
       case "*":
       case "mul":
         res.c = res.a * res.b;
         break;
       case "/":
       case "div":
         if (res.b == 0) {
           return "400 Divide by Zero";
         } else {
           res.c = res.a / res.b;
         }
         break;
       default:
         return "400 Invalid Operator";
     }
   
     return res;
   };
   ```

------
#### [ Python ]

   ```
   import json
   
   
   def lambda_handler(event, context):
       print(event)
   
       try:
           (event['a']) and (event['b']) and (event['op'])
       except KeyError:
           return '400 Invalid Input'
   
       try:
           res = {
               "a": float(
                   event['a']), "b": float(
                   event['b']), "op": event['op']}
       except ValueError:
           return '400 Invalid Operand'
   
       if event['op'] == '+':
           res['c'] = res['a'] + res['b']
       elif event['op'] == '-':
           res['c'] = res['a'] - res['b']
       elif event['op'] == '*':
           res['c'] = res['a'] * res['b']
       elif event['op'] == '/':
           if res['b'] == 0:
               return '400 Divide by Zero'
           else:
               res['c'] = res['a'] / res['b']
       else:
           return '400 Invalid Operator'
   
       return res
   ```

------

1. 在執行角色下，選擇**選擇現有的角色**。

1. 為您先前建立的 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role** 角色輸入角色 ARN。

1. 選擇 **Deploy (部署)**。

 此函數需要 `a` 輸入參數有兩個運算元 (`b` 和 `op`) 和一個運算子 (`event`)。輸入是下列格式的 JSON 物件：

```
{
  "a": "Number" | "String",
  "b": "Number" | "String",
  "op": "String"
}
```

此函數會傳回計算的結果 (`c`) 和輸入。對於無效的輸入，該函數會傳回 null 值或「無效 op」字串做為結果。輸出具有下列 JSON 格式：

```
{
  "a": "Number",
  "b": "Number",
  "op": "String",
  "c": "Number" | "String"
}
```

您應該先在 Lambda 主控台中測試函數，再於後續步驟中將它與 API 整合。

## 測試 `Calc` Lambda 函式
<a name="api-as-lambda-proxy-test-lambda-function-"></a>

以下是在 Lambda 主控台測試 `Calc` 函數的方式：

1. 選擇**測試**標籤。

1. 針對測試事件名稱，輸入 **calc2plus5**。

1. 將測試事件定義取代為下列內容：

   ```
   {
     "a": "2",
     "b": "5",
     "op": "+"
   }
   ```

1. 選擇 **Save** (儲存)。

1. 選擇 **Test (測試)**。

1. 展開 **Execution result: succeeded (執行結果：成功)**。請查看下列事項：

   ```
   {
     "a": 2,
     "b": 5,
     "op": "+",
     "c": 7
   }
   ```

## 建立 `Calc` API
<a name="api-as-lambda-proxy-create-api-resources"></a>

下列程序說明如何為您剛建立的 `Calc` Lambda 函數建立 API。在後續幾節中，您會將資源和方法新增至其中。

**建立 API**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇**組建**。

1.  對於**API 名稱**，輸入 **LambdaCalc**。

1. 在**描述**，請輸入描述。

1. 將 **API 端點類型**保持設定為**區域**。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇 **Create API (建立 API)**。

## 整合 1：建立 `GET` 方法與查詢參數搭配來呼叫 Lambda 函數
<a name="api-as-lambda-proxy-expose-get-method-with-query-strings-to-call-lambda-function"></a>

透過建立 `GET` 方法，將查詢字串參數傳遞至 Lambda 函數，您可以啟用 API，讓其可透過瀏覽器叫用。這種方法很有用，尤其適用於允許開放存取的 API。

在建立 API 之後，請建立資源。一般而言，會根據應用程式邏輯將 API 資源組織為資源樹狀結構。在此步驟中，您會建立 **/calc** 資源。

**建立 **/calc** 資源**

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

1. 讓**代理資源**保持關閉。

1. 將**資源路徑**保持為 `/`。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

透過建立 `GET` 方法，將查詢字串參數傳遞至 Lambda 函數，您可以啟用 API，讓其可透過瀏覽器調用。這種方法很有用，尤其適用於允許開放存取的 API。

在此方法中，Lambda 需要使用 `POST` 請求來叫用任何 Lambda 函數。此範例示範前端方法請求中的 HTTP 方法可以與後端中的整合請求不同。

**建立 `GET` 方法**

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Lambda 函數 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Lambda**。

1. 讓 **AWS 子網域**保持空白。

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

1. 針對**動作類型**，選取**使用路徑覆寫**。這個選項可讓我們指定 [Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) 動作的 ARN，來執行 `Calc` 函數。

1. 針對**路徑覆寫**，輸入 **2015-03-31/functions/arn:aws:lambda:*us-east-2*:*account-id*:function:Calc/invocations**。針對 ** *account-id***，輸入您的 AWS 帳戶 ID。針對 ***us-east-2***，輸入您建立 Lambda 函數 AWS 區域 的 。

1. 針對**執行角色**，輸入 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role** 的角色 ARN。

1. 請勿變更**憑證快取**和**預設逾時**的設定。

1. 選擇**方法請求設定**。

1. 對於**請求驗證程式**，選取**驗證查詢字串參數與標頭**。

   如果用戶端未指定所需參數，則此設定會造成系統傳回錯誤訊息。

1. 選擇 **URL 查詢字串參數**。

   現在，您會在 **/calc** 資源上設定 **GET** 方法的查詢字串參數，用以代表後端 Lambda 函數接收輸入。

   若要建立查詢字串參數，請進行下列操作：

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

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

   1. 開啟**必要**。

   1. 讓**快取**保持關閉。

   重複相同的步驟，並建立名為 **operand2** 的查詢字串和名為 **operator** 的查詢字串。

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

現在，請建立對應範本，以將用戶端提供的查詢字串翻譯為 `Calc` 函數所需的整合請求承載。此範本會將**方法請求**中所宣告的三個查詢字串參數對應至 JSON 物件的指定屬性值，作為後端 Lambda 函數的輸入。轉換過的 JSON 物件將會包含為整合請求承載。

**將輸入參數對應至整合請求**

1. 在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

1. 針對**請求內文傳遞**，選取**未定義範本時 (建議)**。

1. 選擇**對應範本**。

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

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

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

   ```
   {
       "a":  "$input.params('operand1')",
       "b":  "$input.params('operand2')", 
       "op": "$input.params('operator')"   
   }
   ```

1. 選擇**儲存**。

您現在可以測試您的 `GET` 方法，確認它已正確設定，可以叫用 Lambda 函數。

**測試 `GET` 方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 針對**查詢字串**，輸入 **operand1=2&operand2=3&operator=\$1**。

1. 選擇**測試**。

   結果看起來會與下列類似：  
![\[在 API Gateway 中建立 API 作為 Lambda 代理\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_lambda_calc_get_method_test_new_console.png)

## 整合 2：建立 `POST` 方法與 JSON 承載搭配來呼叫 Lambda 函數
<a name="api-as-lambda-proxy-expose-post-method-with-json-body-to-call-lambda-function"></a>

透過建立 `POST` 方法與 JSON 承載搭配來呼叫 Lambda 函數，讓用戶端必須在請求內文中提供後端函數的必要輸入。為了確保用戶端上傳正確的輸入資料，您將在承載上啟用請求驗證。

**建立具有 JSON 承載的 `POST` 方法**

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Lambda 函數 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Lambda**。

1. 讓 **AWS 子網域**保持空白。

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

1. 針對**動作類型**，選取**使用路徑覆寫**。這個選項可讓我們指定 [Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) 動作的 ARN，來執行 `Calc` 函數。

1. 針對**路徑覆寫**，輸入 **2015-03-31/functions/arn:aws:lambda:*us-east-2*:*account-id*:function:Calc/invocations**。針對 ** *account-id***，輸入您的 AWS 帳戶 ID。針對 ***us-east-2***，輸入您建立 Lambda 函數 AWS 區域 的 。

1. 針對**執行角色**，輸入 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role** 的角色 ARN。

1. 請勿變更**憑證快取**和**預設逾時**的設定。

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

現在，請建立**輸入**模型來說明輸入資料結構，並驗證傳入請求內文。

**建立輸入模型**

1. 在主導覽窗格中，選擇**模型**。

1. 選擇**建立模型**。

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

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

   如果找不到相符的內容類型，則不會執行請求驗證。若要使用相同的模型，而不論內容類型為何，請輸入 **\$1default**。

1. 針對**模型結構描述**，輸入下列模型：

   ```
   {
       "type":"object",
       "properties":{
           "a":{"type":"number"},
           "b":{"type":"number"},
           "op":{"type":"string"}
       },
       "title":"input"
   }
   ```

1. 選擇**建立模型**。

您現在要建立**輸出**模型。此模型說明來自後端之計算輸出的資料結構。它可以用來將整合回應資料對應至不同模型。本教學依賴傳遞行為，而且不會使用此模型。

**建立輸出模型**

1. 選擇**建立模型**。

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

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

   如果找不到相符的內容類型，則不會執行請求驗證。若要使用相同的模型，而不論內容類型為何，請輸入 **\$1default**。

1. 針對**模型結構描述**，輸入下列模型：

   ```
   {
       "type":"object",
       "properties":{
           "c":{"type":"number"}
       },
       "title":"output"
   }
   ```

1. 選擇**建立模型**。

您現在會建立**結果**模型。此模型說明所傳回回應資料的資料結構。其會參考 API 中所定義的**輸入**和**輸出**結構描述。

**建立結果模型**

1. 選擇**建立模型**。

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

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

   如果找不到相符的內容類型，則不會執行請求驗證。若要使用相同的模型，而不論內容類型為何，請輸入 **\$1default**。

1. 針對**模型結構描述**，使用您的 *restapi-id* 輸入以下模型。您的 *restapi-id* 會以括號列在以下流程中的主控台頂端：`API Gateway > APIs > LambdaCalc (abc123).`

   ```
   {
       "type":"object",
       "properties":{
           "input":{
               "$ref":"https://apigateway.amazonaws.com/restapis/restapi-id/models/input"
           },
           "output":{
               "$ref":"https://apigateway.amazonaws.com/restapis/restapi-id/models/output"
           }
       },
       "title":"result"
   }
   ```

1. 選擇**建立模型**。

您現在要設定 POST 方法的方法請求，以在傳入請求內文上啟用請求驗證。

**若要針對 POST 方法啟用請求驗證**

1. 在主導覽窗格中，選擇**資源**，然後從資源樹狀目錄中選取 `POST` 方法。

1. 在**方法請求**索引標籤的**方法請求設定**下，選擇**編輯**。

1. 對於**請求驗證程式**，選取**驗證內文**。

1. 選擇**請求內文**，然後選擇**新增模型**。

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

   如果找不到相符的內容類型，則不會執行請求驗證。若要使用相同的模型，而不論內容類型為何，請輸入 **\$1default**。

1. 針對**模型**，選取**輸入**。

1. 選擇**儲存**。

您現在可以測試您的 `POST` 方法，確認它已正確設定，可以叫用 Lambda 函數。

**測試 `POST` 方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 針對**請求內文**，輸入下列 JSON 承載。

   ```
   {
       "a": 1,
       "b": 2,
       "op": "+"
   }
   ```

1. 選擇**測試**。

   您應該會看到下列輸出：

   ```
   {
     "a": 1,
     "b": 2,
     "op": "+",
     "c": 3
   }
   ```

## 整合 3：建立 `GET` 方法與路徑參數搭配來呼叫 Lambda 函數
<a name="api-as-lambda-proxy-expose-get-method-with-path-parameters-to-call-lambda-function"></a>

現在，您將在透過一系列路徑參數所指定的資源上建立 `GET` 方法，來呼叫後端 Lambda 函數。路徑參數值指定 Lambda 函數的輸入資料。您需要使用映射範本將傳入路徑參數值映射至所需的整合請求承載。

產生的 API 資源結構看起來像這樣：

![\[在 API Gateway 中建立 API 作為 Lambda 代理\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_lambda_create_api_resources_new_console.png)


**建立 **/\$1operand1\$1/\$1operand2\$1/\$1operator\$1** 資源**

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

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

1. 針對**資源名稱**，輸入 **\$1operand1\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

1. 針對**資源路徑**，選取 `/calc/{operand1}/`。

1. 針對**資源名稱**，輸入 **\$1operand2\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

1. 針對**資源路徑**，選取 `/calc/{operand1}/{operand2}/`。

1. 針對**資源名稱**，輸入 **\$1operator\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

此時，您要在 API Gateway 主控台中使用內建的 Lambda 整合來設定方法整合。

**設定方法整合**

1. 選取 **/\$1operand1\$1/\$1operand2\$1/\$1operator\$1** 資源，然後選擇**建立方法**。

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

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

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

1. 針對 **Lambda 函數**，選取您建立 Lambda 函數 AWS 區域 的 ，然後輸入 **Calc**。

1. 讓**預設逾時**保持開啟。

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

您現在要建立對應範本，以將建立 **/calc/\$1operand1\$1/\$1operand2\$1/\$1operator\$1** 資源時所宣告的三個 URL 路徑參數對應至 JSON 物件中的指定屬性值。因為 URL 路徑必須是 URL 編碼，所以必須將 division 運算子指定為 `%2F`，而非 `/`。此範本會先將 `%2F` 翻譯為 `'/'`，再將它傳遞給 Lambda 函數。

**建立映射範本**

1. 在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

1. 針對**請求內文傳遞**，選取**未定義範本時 (建議)**。

1. 選擇**對應範本**。

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

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

   ```
   {
      "a": "$input.params('operand1')",
      "b": "$input.params('operand2')",
      "op": #if($input.params('operator')=='%2F')"/"#{else}"$input.params('operator')"#end
   }
   ```

1. 選擇**儲存**。

您現在可以測試您的 `GET` 方法，確認其已正確設定，可以叫用 Lambda 函數，並透過整合回應傳遞原始輸出，而不需要對應。

**測試 `GET` 方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 對於**路徑**，執行下列動作：

   1. 對於 **operand1**，輸入 **1**。

   1. 對於 **operand2**，輸入 **1**。

   1. 對於**運算子**，輸入 **\$1**。

1. 選擇 **Test (測試)**。

1. 結果應如下所示：  
![\[在 API Gateway 主控台測試 GET 方法。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_lambda_calc_get_method_test_path_parm_new_console.png)

接著，您將模型化 `result` 結構描述後面之方法回應承載的資料結構。

在預設情況下，方法回應內文會獲指派空白模型。這會造成傳遞整合回應內文，而不進行對應。不過，當您為一個強型別語言 (例如 Java 或 Objective-C) 產生開發套件時，開發套件使用者將會收到一個空白物件做為結果。為了確保 REST 用戶端和開發套件用戶端都收到所需的結果，您必須使用預先定義的結構描述來模型化回應資料。在這裡，您將定義方法回應內文的模型，以及如何建構對應範本，將整合回應內文翻譯為方法回應內文。

**建立方法回應**

1. 在**方法回應**索引標籤上的**回應 200** 下，選擇**編輯**。

1. 在**請求內文**下，選擇**新增模型**。

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

1. 針對**模型**，選取**結果**。

1. 選擇**儲存**。

設定方法回應內文的模型，可確保將回應資料轉換為特定開發套件的 `result` 物件。為了確保據此映射整合回應資料，您將需要映射範本。

**建立映射範本**

1. 在**整合回應**索引標籤上，於**預設 - 回應**下，選擇**編輯**。

1. 選擇**映射範本**。

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

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

   ```
   #set($inputRoot = $input.path('$'))
   {
     "input" : {
       "a" : $inputRoot.a,
       "b" : $inputRoot.b,
       "op" : "$inputRoot.op"
     },
     "output" : {
       "c" : $inputRoot.c
     }
   }
   ```

1. 選擇**儲存**。

**測試對應範本**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 對於**路徑**，執行下列動作：

   1. 對於 **operand1**，輸入 **1**。

   1. 對於 **operand2**，輸入 **2**。

   1. 對於**運算子**，輸入 **\$1**。

1. 選擇**測試**。

1. 結果如下所示：

   ```
   {
     "input": {
       "a": 1,
       "b": 2,
       "op": "+"
     },
     "output": {
       "c": 3
     }
   }
   ```

此時只能透過 API Gateway 主控台中的**測試**功能來呼叫 API。若要讓 API 可供用戶端使用，您需要部署 API。每當新增、修改或刪除資源或方法、更新資料映射，或更新階段設定時，請一律務必重新部署您的 API。否則，您 API 的用戶端將無法使用新功能或更新，如下所示：

**部署 API**

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **Prod**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

1.  (選用) 針對**階段詳細資訊**下的**調用 URL**，您可以選擇複製圖示以複製 API 的調用 URL。您可以使用此項與 [Postman](https://www.postman.com) 和 [cURL](https://curl.se/) 這類工具搭配，來測試您的 API。

**注意**  
每當新增、修改或刪除資源或方法、更新資料映射，或更新階段設定時，請一律重新部署您的 API。否則，您 API 的用戶端將無法使用新功能或更新。

# 與 Lambda 函數整合之範例 API 的 OpenAPI 定義
<a name="api-as-lambda-proxy-export-swagger-with-extensions"></a>

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

```
{
  "swagger": "2.0",
  "info": {
    "version": "2017-04-20T04:08:08Z",
    "title": "LambdaCalc"
  },
  "host": "uojnr9hd57.execute-api.us-east-1.amazonaws.com",
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/calc": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "operand2",
            "in": "query",
            "required": true,
            "type": "string"
          },
          {
            "name": "operator",
            "in": "query",
            "required": true,
            "type": "string"
          },
          {
            "name": "operand1",
            "in": "query",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            },
            "headers": {
              "operand_1": {
                "type": "string"
              },
              "operand_2": {
                "type": "string"
              },
              "operator": {
                "type": "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator": "Validate query string parameters and headers",
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.operator": "integration.response.body.op",
                "method.response.header.operand_2": "integration.response.body.b",
                "method.response.header.operand_1": "integration.response.body.a"
              },
              "responseTemplates": {
                "application/json": "#set($res = $input.path('$'))\n{\n    \"result\": \"$res.a, $res.b, $res.op => $res.c\",\n  \"a\" : \"$res.a\",\n  \"b\" : \"$res.b\",\n  \"op\" : \"$res.op\",\n  \"c\" : \"$res.c\"\n}"
              }
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "requestTemplates": {
            "application/json": "{\n    \"a\":  \"$input.params('operand1')\",\n    \"b\":  \"$input.params('operand2')\", \n    \"op\": \"$input.params('operator')\"   \n}"
          },
          "type": "aws"
        }
      },
      "post": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "Input",
            "required": true,
            "schema": {
              "$ref": "#/definitions/Input"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-request-validator": "Validate body",
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"a\" : $inputRoot.a,\n  \"b\" : $inputRoot.b,\n  \"op\" : $inputRoot.op,\n  \"c\" : $inputRoot.c\n}"
              }
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_templates",
          "httpMethod": "POST",
          "type": "aws"
        }
      }
    },
    "/calc/{operand1}/{operand2}/{operator}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "operand2",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "operator",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "operand1",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_templates",
          "httpMethod": "POST",
          "requestTemplates": {
            "application/json": "{\n   \"a\": \"$input.params('operand1')\",\n   \"b\": \"$input.params('operand2')\",\n   \"op\": #if($input.params('operator')=='%2F')\"/\"#{else}\"$input.params('operator')\"#end\n   \n}"
          },
          "contentHandling": "CONVERT_TO_TEXT",
          "type": "aws"
        }
      }
    }
  },
  "definitions": {
    "Input": {
      "type": "object",
      "required": [
        "a",
        "b",
        "op"
      ],
      "properties": {
        "a": {
          "type": "number"
        },
        "b": {
          "type": "number"
        },
        "op": {
          "type": "string",
          "description": "binary op of ['+', 'add', '-', 'sub', '*', 'mul', '%2F', 'div']"
        }
      },
      "title": "Input"
    },
    "Output": {
      "type": "object",
      "properties": {
        "c": {
          "type": "number"
        }
      },
      "title": "Output"
    },
    "Result": {
      "type": "object",
      "properties": {
        "input": {
          "$ref": "#/definitions/Input"
        },
        "output": {
          "$ref": "#/definitions/Output"
        }
      },
      "title": "Result"
    }
  },
  "x-amazon-apigateway-request-validators": {
    "Validate body": {
      "validateRequestParameters": false,
      "validateRequestBody": true
    },
    "Validate query string parameters and headers": {
      "validateRequestParameters": true,
      "validateRequestBody": false
    }
  }
}
```

------

# 教學：建立 REST API 做為 Amazon S3 代理
<a name="integrating-api-with-aws-services-s3"></a>

例如，若要示範如何在 API Gateway 中使用 REST API 來代理處理 Amazon S3，本節說明如何建立和設定 REST API 來公開下列 Amazon S3 操作：
+ 在 API 根資源上公開 GET，以[列出發起人的所有 Amazon S3 儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html)。
+ 在 Folder 資源上公開 GET，以[檢視 Amazon S3 儲存貯體中的所有物件清單](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html)。
+ 在 Folder/Item 資源上公開 GET，以[檢視或下載 Amazon S3 儲存貯體中的物件](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)。

 建議您匯入範例 API 作為 Amazon S3 代理，如[做為 Amazon S3 代理之範例 API 的 OpenAPI 定義](api-as-s3-proxy-export-swagger-with-extensions.md)中所示。此範例包含更多已公開的方法。如需如何使用 OpenAPI 定義匯入 API 的說明，請參閱[在 API Gateway 中使用 OpenAPI 開發 REST API](api-gateway-import-api.md)。

**注意**  
 若要整合 API Gateway API 與 Amazon S3，您必須選擇可使用 API Gateway API 與 Amazon S3 服務的區域。如需區域可用性，請參閱 [Amazon API Gateway 端點和配額](https://docs.aws.amazon.com/general/latest/gr/apigateway.html)。

**Topics**
+ [

## 設定 API 叫用 Amazon S3 動作的 IAM 許可
](#api-as-s3-proxy-iam-permissions)
+ [

## 建立 API 資源以代表 Amazon S3 資源
](#api-as-s3-proxy-create-resources)
+ [

## 公開 API 方法來列出發起人的 Amazon S3 儲存貯體
](#api-root-get-as-s3-get-service)
+ [

## 公開 API 方法來存取 Amazon S3 儲存貯體
](#api-folder-operations-as-s3-bucket-actions)
+ [

## 公開 API 方法來存取儲存貯體中的 Amazon S3 物件
](#api-items-in-folder-as-s3-objects-in-bucket)
+ [

# 做為 Amazon S3 代理之範例 API 的 OpenAPI 定義
](api-as-s3-proxy-export-swagger-with-extensions.md)
+ [

# 使用 REST API 用戶端呼叫 API
](api-as-s3-proxy-test-using-postman.md)

## 設定 API 叫用 Amazon S3 動作的 IAM 許可
<a name="api-as-s3-proxy-iam-permissions"></a>

 若要允許 API 調用 Amazon S3 動作，您必須將適當的 IAM 政策附加至 IAM 角色。在此步驟中，您會建立新的 IAM 角色。

**建立 AWS 服務代理執行角色**

1. 登入 AWS 管理主控台 ，並在 https：//[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 開啟 IAM 主控台。

1. 選擇**角色**。

1. 選擇建**立角色**。

1.  在**選取信任的實體類型**下選擇 **AWS 服務**，然後選取 **API Gateway** 並選取**允許 API Gateway 將日誌推送到 CloudWatch Logs**。

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

1. 針對**角色名稱**，輸入 **APIGatewayS3ProxyPolicy**，然後選擇**建立角色**。

1. 在**角色**清單中，選擇您剛剛建立的角色。您可能需要捲動或使用搜尋列來尋找該角色。

1. 針對選取的角色，選取 **許可** 索引標籤。

1. 在下拉式清單中，選擇 **連接政策**。

1. 在搜尋列中輸入 **AmazonS3FullAccess**，並選擇**新增許可**。
**注意**  
本教學課程為了簡單起見，使用受管理政策。最佳實務是，您應建立自己的 IAM 政策以授予所需的最低許可。

1. 記下新建的**角色 ARN**，以在稍後使用。

## 建立 API 資源以代表 Amazon S3 資源
<a name="api-as-s3-proxy-create-resources"></a>

您使用 API 的根 (`/`) 資源做為已驗證發起人之 Amazon S3 儲存貯體的容器。您也會建立 `Folder` 和 `Item` 資源，分別代表特定 Amazon S3 儲存貯體和特定 Amazon S3 物件。發起人會將資料夾名稱和物件金鑰指定為請求 URL 一部分的路徑參數。

**注意**  
當所存取物件的物件金鑰包含 `/` 或任何其他特殊字元時，該字元必須以 URL 編碼。例如，`test/test.txt` 應編碼為 `test%2Ftest.txt`。

**建立可公開 Amazon S3 服務功能的 API 資源**

1.  在 AWS 區域 建立 Amazon S3 儲存貯體的相同 中，建立名為 **MyS3** 的 API。這個 API 的根資源 (**/**) 代表 Amazon S3 服務。在此步驟中，您會另外建立兩個資源 **/\$1folder\$1** 和 **/\$1item\$1**。

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

1. 讓**代理資源**保持關閉。

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

1. 針對**資源名稱**，輸入 **\$1folder\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持未核取狀態。

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

1. 選取 **/\$1folder\$1** 資源，然後選擇**建立資源**。

1. 使用上述步驟建立名為 **\$1item\$1** 的 **/\$1folder\$1** 子資源。

   您的最終 API 應會如下所示：

      
![\[在 API Gateway 中建立 API 作為 Amazon S3 代理\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_s3_create_api-resources_new_console.png)

## 公開 API 方法來列出發起人的 Amazon S3 儲存貯體
<a name="api-root-get-as-s3-get-service"></a>

取得發起人的 Amazon S3 儲存貯體清單包含在 Amazon S3 上呼叫 [GET 服務](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html)動作。在 API 的根資源 (**/**) 上，建立 GET 方法。設定 GET 方法以與 Amazon S3 整合，如下所示。

**建立和初始化 API 的 `GET /` 方法**

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Amazon S3 儲存貯 AWS 區域 體的 。

1. 針對 **AWS 服務**，選取 **Amazon Simple Storage Service**。

1. 讓 **AWS 子網域**保持空白。

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

1. 針對**動作類型**，選取**使用路徑覆寫**。

   使用路徑覆寫，API Gateway 會將用戶端請求轉送給 Amazon S3 以作為對應的 [Amazon S3 REST API 路徑樣式請求](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAPI.html)；其中，Amazon S3 資源是以 `s3-host-name/bucket/key` 模式的資源路徑表示。API Gateway 會設定 `s3-host-name`，並將用戶端指定的 `bucket` 和 `key` 從用戶端傳遞給 Amazon S3。

1. 針對**路徑覆寫**，輸入 **/**。

1. 針對**執行角色**，輸入 **APIGatewayS3ProxyPolicy** 的角色 ARN。

1. 選擇**方法請求設定**。

   您可以使用方法請求設定來控制誰可以呼叫此 API 方法。

1. 針對**授權**，從下拉式功能表中選取 `AWS_IAM`。

      
![\[宣告方法回應類型\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_s3_setup_method_request_authorization_new_console.png)

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

此設定會整合前端 `GET https://your-api-host/stage/` 請求與後端 `GET https://your-s3-host/`。

 為了讓您的 API 將成功回應和例外狀況正確地傳回給發起人，請在**方法回應**中宣告 200、400 和 500 回應。您使用 200 回應做為預設映射；因此，會將未在這裡宣告的狀態碼後端回應當成 200 回應傳回給發起人。

**宣告 `GET /` 方法的回應類型**

1.  在**方法回應**索引標籤上的**回應 200** 下，選擇**編輯**。

1. 選擇**新增標頭**，然後執行下列動作：

   1. 針對**標頭名稱**，輸入 **Content-Type**。

   1. 選擇**新增標頭**。

   重複這些步驟以建立 **Timestamp** 標頭和 **Content-Length** 標頭。

1. 選擇**儲存**。

1. 在**方法回應**索引標籤上的**方法回應**下，選擇**建立回應**。

1. 針對 **HTTP 狀態碼**，輸入 **400**。

   您未針對此回應設定任何標頭。

1. 選擇**儲存**。

1. 重複以下步驟以建立 500 回應。

   您未針對此回應設定任何標頭。

因為來自 Amazon S3 的成功整合回應傳回儲存貯體清單做為 XML 承載，而來自 API Gateway 的預設方法回應傳回 JSON 承載，所以您必須將後端 Content-Type 標頭參數值映射至前端相應實物。否則，回應內文實際上是 XML 字串時，用戶端將會收到內容類型的 `application/json`。下列程序示範如何設定此項目。此外，您也想要向用戶端顯示其他標頭參數 (例如 Date 和 Content-Length)。

**設定 GET / 方法的回應標頭對應**

1. 在**整合回應**索引標籤上，於**預設 - 回應**下，選擇**編輯**。

1. 針對 **Content-Length** 標頭，輸入 **integration.response.header.Content-Length** 作為對應值。

1. 針對 **Content-Type** 標頭，輸入 **integration.response.header.Content-Type** 作為對應值。

1. 針對**時間戳記**標頭，輸入 **integration.response.header.Date** 作為對應值。

1. 選擇**儲存**。結果應類似以下內容：

      
![\[將整合回應標頭對應至方法回應標頭\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_s3_setup_integration_response_headers_new_console.png)

1. 在**整合回應**索引標籤上的**整合回應**下，選擇**建立回應**。

1. 對於 **HTTP 狀態 regex**，輸入 **4\$1d\$12\$1**。這會將所有 4xx HTTP 回應狀態碼對應到方法回應。

1. 針對**方法回應狀態碼**，選取 **400**。

1. 選擇**建立**。

1. 重複下列步驟，為 500 方法回應建立整合回應。對於 **HTTP 狀態 regex**，輸入 **5\$1d\$12\$1**。

您最好測試到目前為止已設定的 API。

**測試 `GET /` 方法**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 選擇**測試**。結果應如下圖所示：

      
![\[測試 API 根 GET 儲存貯體結果\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_s3_test_root_get_result_new_console.png)

## 公開 API 方法來存取 Amazon S3 儲存貯體
<a name="api-folder-operations-as-s3-bucket-actions"></a>

為了使用 Amazon S3 儲存貯體，您在/\$1folder\$1 資源上公開 `GET` 方法，以列出儲存貯體中的物件。這些說明與「[公開 API 方法來列出發起人的 Amazon S3 儲存貯體](#api-root-get-as-s3-get-service)」中所述的說明類似。如需更多方法，您可以在此處 ([做為 Amazon S3 代理之範例 API 的 OpenAPI 定義](api-as-s3-proxy-export-swagger-with-extensions.md)) 匯入範例 API。

**在資料夾資源上公開 GET 方法**

1. 選取 **/\$1folder\$1** 資源，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Amazon S3 儲存貯 AWS 區域 體的 。

1. 針對 **AWS 服務**，選取 **Amazon Simple Storage Service**。

1. 讓 **AWS 子網域**保持空白。

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

1. 針對**動作類型**，選取**使用路徑覆寫**。

1. 針對**路徑覆寫**，輸入 **\$1bucket\$1**。

1. 針對**執行角色**，輸入 **APIGatewayS3ProxyPolicy** 的角色 ARN。

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

您在 Amazon S3 端點 URL 中設定 `{folder}` 路徑參數。您需要將方法請求的 `{folder}` 路徑參數對應至整合請求的 `{bucket}` 路徑參數。

**將 `{folder}` 對應至 `{bucket}`**

1.  在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

1. 選擇 **URL 路徑參數**，然後選擇**新增路徑參數**。

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

1. 對於**映射自**，輸入 **method.request.path.folder**。

1. 選擇**儲存**。

現在，測試您的 API。

**測試 `/{folder} GET` 方法。**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 在**路徑**下，針對**資料夾**，輸入儲存貯體的名稱。

1. 選擇**測試**。

   測試結果將包含儲存貯體中的物件清單。

      
![\[測試 GET 方法來建立 Amazon S3 儲存貯體。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_s3_test_api_folder_get_new_console.png)

## 公開 API 方法來存取儲存貯體中的 Amazon S3 物件
<a name="api-items-in-folder-as-s3-objects-in-bucket"></a>

Amazon S3 支援 GET、DELETE、HEAD、OPTIONS、POST 和 PUT 動作來存取和管理特定儲存貯體中的物件。在本教學課程中，您會在 `{folder}/{item}` 資源上公開 `GET` 方法，以從儲存貯體取得映像。如需 `{folder}/{item}` 資源的更多應用，請參閱範例 API ([做為 Amazon S3 代理之範例 API 的 OpenAPI 定義](api-as-s3-proxy-export-swagger-with-extensions.md))。

**在項目資源上公開 GET 方法**

1. 選取 **/\$1item\$1** 資源，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Amazon S3 儲存貯 AWS 區域 體的 。

1. 針對 **AWS 服務**，選取 **Amazon Simple Storage Service**。

1. 讓 **AWS 子網域**保持空白。

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

1. 針對**動作類型**，選取**使用路徑覆寫**。

1. 針對**路徑覆寫**，輸入 **\$1bucket\$1/\$1object\$1**。

1. 針對**執行角色**，輸入 **APIGatewayS3ProxyPolicy** 的角色 ARN。

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

您在 Amazon S3 端點 URL 中設定 `{folder}` 和 `{item}` 路徑參數。您需要將方法請求的 路徑參數映射至整合請求的路徑參數。

請於本步驟執行以下操作：
+ 將方法請求的 `{folder}` 路徑參數對應至整合請求的 `{bucket}` 路徑參數。
+ 將方法請求的 `{item}` 路徑參數對應至整合請求的 `{object}` 路徑參數。

**將 `{folder}` 對應至 `{bucket}` 並將 `{item}` 對應至 `{object}`**

1.  在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

1. 選擇 **URL 路徑參數**。

1. 選擇**新增路徑參數**。

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

1. 對於**映射自**，輸入 **method.request.path.folder**。

1. 選擇**新增路徑參數**。

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

1. 對於**映射自**，輸入 **method.request.path.item**。

1. 選擇**儲存**。

**測試 `/{folder}/{object} GET` 方法。**

1. 選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

1. 在**路徑**下，針對**資料夾**，輸入儲存貯體的名稱。

1. 在**路徑**下，針對**項目**，輸入項目的名稱。

1. 選擇**測試**。

   回應內文會包含該項目的內容。

      
![\[測試 GET 方法來建立 Amazon S3 儲存貯體。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/aws_proxy_s3_test_api_item_get_new_console.png)

   請求會正確地傳回 ("Hello world") 的純文字作為指定 Amazon S3 儲存貯體 (amzn-s3-demo-bucket) 中所指定檔案 (test.txt) 的內容。

 若要下載或上傳二進位檔案，而二進位檔案在 API Gateway 中視為 utf-8 編碼 JSON 內容以外的任何事項，則需要額外的 API 設定。這概述如下：

**從 S3 下載或上傳二進位檔案**

1.  將受影響檔案的媒體類型註冊到 API 的 binaryMediaTypes。您可以在主控台中執行這項操作：

   1. 選擇 API 的 **API 設定**。

   1. 在**二進位媒體類型**下，選擇**管理媒體類型**。

   1. 選擇**新增二進位媒體類型**，然後輸入所需的媒體類型，例如 `image/png`。

   1. 選擇**儲存變更**來儲存設定。

1. 將 `Content-Type` (進行上傳) 和 (或) `Accept` (進行下載) 標頭新增至方法請求，以要求用戶端指定所需的二進位媒體類型，並將其對應至整合請求。

1. 在整合請求 (進行上傳) 和整合回應 (進行下載) 中，將 **Content Handling (內容處理)** 設定為 `Passthrough`。請確定未定義受影響內容類型的對應範本。如需詳細資訊，請參閱[API Gateway 中用於 REST API 的資料轉換](rest-api-data-transformations.md)。

承載大小上限為 10 MB。請參閱[在 API Gateway 中設定和執行 REST API 的配額](api-gateway-execution-service-limits-table.md)。

確定 Amazon S3 上的檔案具有新增為檔案中繼資料的正確內容類型。針對可串流媒體內容，`Content-Disposition:inline` 也可能需要新增至中繼資料。

如需 API Gateway 中二進位支援的詳細資訊，請參閱[API Gateway 中的內容類型轉換](api-gateway-payload-encodings-workflow.md)。

# 做為 Amazon S3 代理之範例 API 的 OpenAPI 定義
<a name="api-as-s3-proxy-export-swagger-with-extensions"></a>

下列 OpenAPI 定義會說明以 Amazon S3 代理形式來運作的 API。此 API 包含的 Amazon S3 操作比您在教學課程中所建立的 API 還多。下列方法會在 OpenAPI 定義中公開：
+ 在 API 根資源上公開 GET，以[列出發起人的所有 Amazon S3 儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html)。
+ 在 Folder 資源上公開 GET，以[檢視 Amazon S3 儲存貯體中的所有物件清單](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html)。
+ 在 Folder 資源上公開 PUT，以[將儲存貯體新增至 Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)。
+ 在 Folder 資源上公開 DELETE，以[從 Amazon S3 移除儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html)。
+ 在 Folder/Item 資源上公開 GET，以[檢視或下載 Amazon S3 儲存貯體中的物件](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)。
+ 在 Folder/Item 資源上公開 PUT，以[將物件上傳至 Amazon S3 儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)。
+ 在 Folder/Item 資源上公開 HEAD，以[取得 Amazon S3 儲存貯體中的物件中繼資料](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)。
+ 在 Folder/Item 資源上公開 DELETE，以[移除 Amazon S3 儲存貯體中的物件](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html)。

如需如何使用 OpenAPI 定義匯入 API 的說明，請參閱[在 API Gateway 中使用 OpenAPI 開發 REST API](api-gateway-import-api.md)。

如需如何建立類似 API 的指示，請參閱[教學：建立 REST API 做為 Amazon S3 代理](integrating-api-with-aws-services-s3.md)。

若要了解如何使用支援 IAM 授權的 [Postman](https://www.postman.com/) AWS 叫用此 API，請參閱 [使用 REST API 用戶端呼叫 API](api-as-s3-proxy-test-using-postman.md)。

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

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-10-13T23:04:43Z",
    "title": "MyS3"
  },
  "host": "9gn28ca086.execute-api.{region}.amazonaws.com",
  "basePath": "/S3",
  "schemes": [
    "https"
  ],
  "paths": {
    "/": {
      "get": {
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Length": {
                "type": "string"
              },
              "Timestamp": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type",
                "method.response.header.Content-Length": "integration.response.header.Content-Length",
                "method.response.header.Timestamp": "integration.response.header.Date"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path//",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "GET",
          "type": "aws"
        }
      }
    },
    "/{folder}": {
      "get": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Length": {
                "type": "string"
              },
              "Date": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type",
                "method.response.header.Date": "integration.response.header.Date",
                "method.response.header.Content-Length": "integration.response.header.content-length"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.bucket": "method.request.path.folder"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "GET",
          "type": "aws"
        }
      },
      "put": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": false,
            "type": "string"
          },
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Length": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type",
                "method.response.header.Content-Length": "integration.response.header.Content-Length"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.bucket": "method.request.path.folder",
            "integration.request.header.Content-Type": "method.request.header.Content-Type"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "PUT",
          "type": "aws"
        }
      },
      "delete": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Date": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type",
                "method.response.header.Date": "integration.response.header.Date"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.bucket": "method.request.path.folder"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "DELETE",
          "type": "aws"
        }
      }
    },
    "/{folder}/{item}": {
      "get": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "item",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "content-type": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.content-type": "integration.response.header.content-type",
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.object": "method.request.path.item",
            "integration.request.path.bucket": "method.request.path.folder"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "GET",
          "type": "aws"
        }
      },
      "head": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "item",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Length": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type",
                "method.response.header.Content-Length": "integration.response.header.Content-Length"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.object": "method.request.path.item",
            "integration.request.path.bucket": "method.request.path.folder"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "HEAD",
          "type": "aws"
        }
      },
      "put": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": false,
            "type": "string"
          },
          {
            "name": "item",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Length": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type",
                "method.response.header.Content-Length": "integration.response.header.Content-Length"
              }
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.object": "method.request.path.item",
            "integration.request.path.bucket": "method.request.path.folder",
            "integration.request.header.Content-Type": "method.request.header.Content-Type"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "PUT",
          "type": "aws"
        }
      },
      "delete": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "item",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "folder",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Length": {
                "type": "string"
              },
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response"
          },
          "500": {
            "description": "500 response"
          }
        },
        "security": [
          {
            "sigv4": []
          }
        ],
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200"
            },
            "5\\d{2}": {
              "statusCode": "500"
            }
          },
          "requestParameters": {
            "integration.request.path.object": "method.request.path.item",
            "integration.request.path.bucket": "method.request.path.folder"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "DELETE",
          "type": "aws"
        }
      }
    }
  },
  "securityDefinitions": {
    "sigv4": {
      "type": "apiKey",
      "name": "Authorization",
      "in": "header",
      "x-amazon-apigateway-authtype": "awsSigv4"
    }
  },
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

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

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "MyS3",
    "version" : "2016-10-13T23:04:43Z"
  },
  "servers" : [ {
    "url" : "https://9gn28ca086.execute-api.{region}.amazonaws.com/{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "S3"
      }
    }
  } ],
  "paths" : {
    "/{folder}" : {
      "get" : {
        "parameters" : [ {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Content-Length" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Date" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "GET",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.Content-Type" : "integration.response.header.Content-Type",
                "method.response.header.Date" : "integration.response.header.Date",
                "method.response.header.Content-Length" : "integration.response.header.content-length"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.bucket" : "method.request.path.folder"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      },
      "put" : {
        "parameters" : [ {
          "name" : "Content-Type",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Content-Length" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "PUT",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.Content-Type" : "integration.response.header.Content-Type",
                "method.response.header.Content-Length" : "integration.response.header.Content-Length"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.bucket" : "method.request.path.folder",
            "integration.request.header.Content-Type" : "method.request.header.Content-Type"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      },
      "delete" : {
        "parameters" : [ {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Date" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "DELETE",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.Content-Type" : "integration.response.header.Content-Type",
                "method.response.header.Date" : "integration.response.header.Date"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.bucket" : "method.request.path.folder"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      }
    },
    "/{folder}/{item}" : {
      "get" : {
        "parameters" : [ {
          "name" : "item",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "content-type" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "GET",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.content-type" : "integration.response.header.content-type",
                "method.response.header.Content-Type" : "integration.response.header.Content-Type"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.object" : "method.request.path.item",
            "integration.request.path.bucket" : "method.request.path.folder"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      },
      "put" : {
        "parameters" : [ {
          "name" : "Content-Type",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "item",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Content-Length" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "PUT",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.Content-Type" : "integration.response.header.Content-Type",
                "method.response.header.Content-Length" : "integration.response.header.Content-Length"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.object" : "method.request.path.item",
            "integration.request.path.bucket" : "method.request.path.folder",
            "integration.request.header.Content-Type" : "method.request.header.Content-Type"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      },
      "delete" : {
        "parameters" : [ {
          "name" : "item",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Content-Length" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "DELETE",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200"
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.object" : "method.request.path.item",
            "integration.request.path.bucket" : "method.request.path.folder"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      },
      "head" : {
        "parameters" : [ {
          "name" : "item",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "folder",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Content-Length" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "HEAD",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path/{bucket}/{object}",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.Content-Type" : "integration.response.header.Content-Type",
                "method.response.header.Content-Length" : "integration.response.header.Content-Length"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "requestParameters" : {
            "integration.request.path.object" : "method.request.path.item",
            "integration.request.path.bucket" : "method.request.path.folder"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      }
    },
    "/" : {
      "get" : {
        "responses" : {
          "400" : {
            "description" : "400 response",
            "content" : { }
          },
          "500" : {
            "description" : "500 response",
            "content" : { }
          },
          "200" : {
            "description" : "200 response",
            "headers" : {
              "Content-Length" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Timestamp" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "Content-Type" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "credentials" : "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "httpMethod" : "GET",
          "uri" : "arn:aws:apigateway:us-west-2:s3:path//",
          "responses" : {
            "4\\d{2}" : {
              "statusCode" : "400"
            },
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.Content-Type" : "integration.response.header.Content-Type",
                "method.response.header.Content-Length" : "integration.response.header.Content-Length",
                "method.response.header.Timestamp" : "integration.response.header.Date"
              }
            },
            "5\\d{2}" : {
              "statusCode" : "500"
            }
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "aws"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Empty" : {
        "title" : "Empty Schema",
        "type" : "object"
      }
    }
  }
}
```

------

# 使用 REST API 用戶端呼叫 API
<a name="api-as-s3-proxy-test-using-postman"></a>

為了提供end-to-end教學課程，我們現在示範如何使用支援 IAM 授權的 [Postman](https://www.postman.com/) AWS 呼叫 API。<a name="api-as-s3-proxy-test-using-postman-steps"></a>

**使用 Postman 呼叫 Amazon S3 代理 API**

1. 部署或重新部署 API。請記下 API 的基本 URL，而此 API 顯示在**階段編輯器**頂端的**呼叫 URL** 旁邊。

1. 啟動 Postman。

1. 選擇**授權**，然後選擇 `AWS Signature`。在 **AccessKey** 和 **SecretKey** 輸入欄位中，分別輸入 IAM 使用者的存取金鑰 ID 和私密存取金鑰。在**AWS 區域**文字方塊中輸入要部署 API 的 AWS 區域 。在**服務名稱**輸入欄位中，輸入 `execute-api`。

   您可以從 IAM 管理主控台之 IAM 使用者帳戶的 **Security Credentials (安全登入資料)** 標籤中建立一對金鑰。

1. 將名為 `amzn-s3-demo-bucket` 的儲存貯體新增至 `{region}` 區域中的 Amazon S3 帳戶：

   1. 從下拉式方法清單中選擇 **PUT**，並輸入方法 URL (`https://api-id.execute-api.aws-region.amazonaws.com/stage/folder-name`

   1. 將 `Content-Type` 標頭值設定為 `application/xml`。您可能需要先刪除任何現有標頭，再設定內容類型。

   1. 選擇**內文**選單項目，並輸入下列 XML 片段做為請求內文：

      ```
      <CreateBucketConfiguration> 
        <LocationConstraint>{region}</LocationConstraint> 
      </CreateBucketConfiguration>
      ```

   1. 選擇**傳送**，以提交請求。如果成功，您應該會收到具有空承載的 `200 OK` 回應。

1. 若要將文字檔案新增至儲存貯體，請遵循上述說明操作。如果您在 URL 中指定 **amzn-s3-demo-bucket** 的儲存貯體名稱 `{folder}` 和 **Readme.txt** 的檔案名稱 `{item}`，並提供字串 **Hello, World\$1** 做為檔案內容 (因此其會成為請求承載)，則請求會如下所示：

   ```
   PUT /S3/amzn-s3-demo-bucket/Readme.txt HTTP/1.1
   Host: 9gn28ca086.execute-api.{region}.amazonaws.com
   Content-Type: application/xml
   X-Amz-Date: 20161015T062647Z
   Authorization: AWS4-HMAC-SHA256 Credential=access-key-id/20161015/{region}/execute-api/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=ccadb877bdb0d395ca38cc47e18a0d76bb5eaf17007d11e40bf6fb63d28c705b
   Cache-Control: no-cache
   Postman-Token: 6135d315-9cc4-8af8-1757-90871d00847e
   
   Hello, World!
   ```

   如果一切順利，您應該會收到含有空白承載的 `200 OK` 回應。

1. 若要取得剛剛新增至 `Readme.txt` 儲存貯體之 `amzn-s3-demo-bucket` 檔案的內容，請執行 GET 請求，如下所示：

   ```
   GET /S3/amzn-s3-demo-bucket/Readme.txt HTTP/1.1
   Host: 9gn28ca086.execute-api.{region}.amazonaws.com
   Content-Type: application/xml
   X-Amz-Date: 20161015T063759Z
   Authorization: AWS4-HMAC-SHA256 Credential=access-key-id/20161015/{region}/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=ba09b72b585acf0e578e6ad02555c00e24b420b59025bc7bb8d3f7aed1471339
   Cache-Control: no-cache
   Postman-Token: d60fcb59-d335-52f7-0025-5bd96928098a
   ```

   如果成功，您應該會收到具有 `200 OK` 字串做為承載的 `Hello, World!` 回應。

1. 若要列出 `amzn-s3-demo-bucket` 儲存貯體中的項目，請提交下列請求：

   ```
   GET /S3/amzn-s3-demo-bucket HTTP/1.1
   Host: 9gn28ca086.execute-api.{region}.amazonaws.com
   Content-Type: application/xml
   X-Amz-Date: 20161015T064324Z
   Authorization: AWS4-HMAC-SHA256 Credential=access-key-id/20161015/{region}/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=4ac9bd4574a14e01568134fd16814534d9951649d3a22b3b0db9f1f5cd4dd0ac
   Cache-Control: no-cache
   Postman-Token: 9c43020a-966f-61e1-81af-4c49ad8d1392
   ```

   如果成功，除非先將更多檔案新增至儲存貯體再提交此請求，否則您應該會收到 `200 OK` 回應，而其 XML 承載顯示所指定儲存貯體中的單一項目。

   ```
   <?xml version="1.0" encoding="UTF-8"?>
   <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
       <Name>apig-demo-5</Name>
       <Prefix></Prefix>
       <Marker></Marker>
       <MaxKeys>1000</MaxKeys>
       <IsTruncated>false</IsTruncated>
       <Contents>
           <Key>Readme.txt</Key>
           <LastModified>2016-10-15T06:26:48.000Z</LastModified>
           <ETag>"65a8e27d8879283831b664bd8b7f0ad4"</ETag>
           <Size>13</Size>
           <Owner>
               <ID>06e4b09e9d...603addd12ee</ID>
               <DisplayName>user-name</DisplayName>
           </Owner>
           <StorageClass>STANDARD</StorageClass>
       </Contents>
   </ListBucketResult>
   ```

**注意**  
若要上傳或下載影像，您需要將內容處理設定為 CONVERT\$1TO\$1BINARY。

# 教學課程：建立 REST API 做為 Amazon Kinesis 代理
<a name="integrating-api-with-aws-services-kinesis"></a>

本頁面說明如何建立和設定與 `AWS` 類型整合的 REST API，以存取 Kinesis。

**注意**  
 若要整合 API Gateway API 與 Kinesis，您必須選擇可使用 API Gateway API 與 Kinesis 服務的區域。如需區域可用性，請參閱[服務端點和配額](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)。

 基於說明，我們建立範例 API，讓用戶端執行下列操作：

1. 列出 Kinesis 中的使用者可用串流 

1. 建立、說明或刪除指定的串流

1. 從指定的串流讀取資料記錄或將資料記錄寫入其中

 為了達成先前的任務，API 會分別公開各種資源的方法來呼叫下列項目：

1. Kinesis 中的 `ListStreams` 動作 

1. `CreateStream`、`DescribeStream` 或 `DeleteStream` 動作

1. Kinesis 中的 `GetRecords` 或 `PutRecords` (包含 `PutRecord`) 動作

 具體而言，我們會如下建置 API：
+  在 API `/streams` 資源上公開 HTTP GET 方法，並在 Kinesis 中整合此方法與 [ListStreams](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_ListStreams.html) 動作，以列出發起人帳戶中的串流。
+  在 API `/streams/{stream-name}` 資源上公開 HTTP POST 方法，並在 Kinesis 中整合此方法與 [CreateStream](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_CreateStream.html) 動作，以在發起人帳戶中建立具名串流。
+  在 API `/streams/{stream-name}` 資源上公開 HTTP GET 方法，並在 Kinesis 中整合此方法與 [DescribeStream](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_DescribeStream.html) 動作，以說明發起人帳戶中的具名串流。
+  在 API `/streams/{stream-name}` 資源上公開 HTTP DELETE 方法，並在 Kinesis 中整合此方法與 [DeleteStream](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_DeleteStream.html) 動作，以刪除發起人帳戶中的串流。
+  在 API 的 `/streams/{stream-name}/record` 資源上公開 HTTP PUT 方法，並在 Kinesis 中整合此方法與 [PutRecord](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html) 動作。這可讓用戶端將單一資料記錄新增至具名串流。
+  在 API 的 `/streams/{stream-name}/records` 資源上公開 HTTP PUT 方法，並在 Kinesis 中整合此方法與 [PutRecords](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html) 動作。這可讓用戶端將資料記錄清單新增至具名串流。
+  在 API `/streams/{stream-name}/records` 資源上公開 HTTP GET 方法，並在 Kinesis 中整合此方法與 [GetRecords](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html) 動作。這可讓用戶端使用指定的碎片迭代運算來列出具名串流中的資料記錄。碎片迭代運算指定從中循序開始讀取資料記錄的碎片位置。
+  在 API `/streams/{stream-name}/sharditerator` 資源上公開 HTTP GET 方法，並在 Kinesis 中整合此方法與 [GetShardIterator](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetShardIterator.html) 動作。必須向 Kinesis 中的 `ListStreams` 動作提供此 helper 方法。

 您可以將這裡看到的說明套用至其他 Kinesis 動作。如需完整 Kinesis 動作清單，請參閱 [Amazon Kinesis API 參考](https://docs.aws.amazon.com/kinesis/latest/APIReference/Welcome.html)。

 除了使用 API Gateway 主控台來建立範例 API 之外，您還可以使用 API Gateway​ [Import API](https://docs.aws.amazon.com/apigateway/latest/api/API_ImportRestApi.html)，以將範例 API 匯入至 API Gateway。如需如何使用 Import API 的資訊，請參閱「[在 API Gateway 中使用 OpenAPI 開發 REST API](api-gateway-import-api.md)」。

## 建立 API 的 IAM 角色和政策來存取 Kinesis
<a name="integrate-with-kinesis-create-iam-role-and-policy"></a>

 若要允許 API 叫用 Kinesis 動作，您必須將適當的 IAM 政策附加至 IAM 角色。在此步驟中，您會建立新的 IAM 角色。

**建立 AWS 服務代理執行角色**

1. 登入 AWS 管理主控台 ，並在 https：//[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 開啟 IAM 主控台。

1. 選擇**角色**。

1. 選擇建**立角色**。

1.  在**選取信任的實體類型**下選擇 **AWS 服務**，然後選取 **API Gateway** 並選取**允許 API Gateway 將日誌推送到 CloudWatch Logs**。

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

1. 針對**角色名稱**，輸入 **APIGatewayKinesisProxyPolicy**，然後選擇**建立角色**。

1. 在**角色**清單中，選擇您剛剛建立的角色。您可能需要捲動或使用搜尋列來尋找該角色。

1. 針對選取的角色，選取 **許可** 索引標籤。

1. 在下拉式清單中，選擇 **連接政策**。

1. 在搜尋列中輸入 **AmazonKinesisFullAccess**，並選擇**新增許可**。
**注意**  
本教學課程為了簡單起見，使用受管理政策。最佳實務是，您應建立自己的 IAM 政策以授予所需的最低許可。

1. 記下新建的**角色 ARN**，以在稍後使用。

## 建立 API 以做為 Kinesis 代理
<a name="api-gateway-create-api-as-kinesis-proxy"></a>

使用下列步驟可在 API Gateway 主控台中建立 API。

**建立 API 做為 Kinesis AWS 的服務代理**

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

1. 如果這是您第一次使用 API Gateway，您會看到服務功能的介紹頁面。在 **REST API** 下方，選擇 **Build (組建)**。當 **Create Example API (建立範例 API)** 快顯出現時，選擇 **OK (確定)**。

   如果這不是第一次使用 API Gateway，請選擇 **Create API (建立 API)**。在 **REST API** 下方，選擇 **Build (組建)**。

1. 選擇 **New API (新增 API)**。

1. 在 **API name (API 名稱)** 中，輸入 **KinesisProxy**。對於所有其他欄位，請保留預設值。

1. 在**描述**，請輸入描述。

1. 針對 **IP 位址類型**，選擇 **IPv4**。

1. 選擇 **Create API (建立 API)**。

 建立 API 之後，API Gateway 主控台會顯示 **Resources (資源)** 頁面，其中只包含 API 的根 (`/`) 資源。

## 列出 Kinesis 中的串流
<a name="api-gateway-list-kinesis-streams"></a>

 Kinesis 透過下列 REST API 呼叫來支援 `ListStreams` 動作：

```
POST /?Action=ListStreams HTTP/1.1
Host: kinesis.<region>.<domain>
Content-Length: <PayloadSizeBytes>
User-Agent: <UserAgentString>
Content-Type: application/x-amz-json-1.1
Authorization: <AuthParams>
X-Amz-Date: <Date>
        
{
   ...
}
```

在上面的 REST API 請求中，動作指定於 `Action` 查詢參數中。或者，您可以改為在 `X-Amz-Target` 標頭中指定動作：

```
POST / HTTP/1.1
Host: kinesis.<region>.<domain>
Content-Length: <PayloadSizeBytes>
User-Agent: <UserAgentString>
Content-Type: application/x-amz-json-1.1
Authorization: <AuthParams>
X-Amz-Date: <Date>
X-Amz-Target: Kinesis_20131202.ListStreams        
{
   ...
}
```

在本教學中，我們使用查詢參數來指定動作。

若要在 API 中公開 Kinesis 動作，請將 `/streams` 資源新增至 API 根。然後在資源上設定 `GET` 方法，並整合此方法與 Kinesis 的 `ListStreams` 動作。

下列程序說明如何使用 API Gateway 主控台來列出 Kinesis 串流。

**使用 API Gateway 主控台來列出 Kinesis 串流**

1. 選取 `/` 資源，然後選擇**建立資源**。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

1.  選擇 `/streams` 資源，然後選擇**建立方法**，然後執行下列動作：

   1. 針對**方法類型**，選取 **GET**。
**注意**  
用戶端所呼叫方法的 HTTP 動詞可能會與後端所需整合的 HTTP 動詞不同。我們在這裡選取 `GET`，因為列出串流直覺上就是 READ 操作。

   1. 針對**整合類型**，選取 **AWS 服務**。

   1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

   1. 針對 **AWS 服務**，選取 **Kinesis**。

   1. 讓 **AWS 子網域**保持空白。

   1. 針對 **HTTP method (HTTP 方法)**，選擇 **POST**。
**注意**  
我們在這裡選擇 `POST`，因為 Kinesis 需要使用它來叫用 `ListStreams` 動作。

   1. 針對**動作類型**，選擇**使用動作名稱**。

   1. 針對**動作名稱**，輸入 **ListStreams**。

   1. 針對**執行角色**，輸入執行角色的 ARN。

   1. 保留**內容處理**之**傳遞**的預設值。

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

1. 在**整合請求**索引標籤上，於**整合請求設定**下，選擇**編輯**。

1. 針對**請求內文傳遞**，選取**未定義範本時 (建議)**。

1.  選擇 **URL 請求標頭參數**，然後執行下列動作：

   1. 選擇**新增請求標頭參數**。

   1. 對於**名稱**，輸入 **Content-Type**。

   1. 對於**映射自**，輸入 **'application/x-amz-json-1.1'**。

    我們會使用請求參數對應將 `Content-Type` 標頭設定為靜態值 `'application/x-amz-json-1.1'`，通知 Kinesis 有關輸入是特定版本的 JSON。

1. 選擇**對應範本**，然後選擇**新增對應範本**，並執行下列動作：

   1. 針對 **Content-Type**，輸入 **application/json**。

   1. 針對**範本內文**，輸入 **\$1\$1**。

   1. 選擇**儲存**。

    [ListStreams](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_ListStreams.html#API_ListStreams_RequestSyntax) 請求採用下列 JSON 格式的承載：

   ```
   {
       "ExclusiveStartStreamName": "string",
       "Limit": number
   }
   ```

   不過，屬性是選用的。若要使用預設值，我們在這裡選擇空的 JSON 承載。

1. 測試 **/streams** 資源上的 GET 方法，以在 Kinesis 中叫用 `ListStreams` 動作：

   選擇**測試**標籤。您可能需要選擇向右箭頭按鈕才能顯示此索引標籤。

   選擇**測試**以測試您的方法。

    如果您已經在 Kinesis 中建立兩個名為 "myStream" 和 "yourStream" 的串流，則成功測試會傳回包含下列承載的 200 OK 回應：

   ```
   {
        "HasMoreStreams": false,
        "StreamNames": [
            "myStream",
            "yourStream"
        ]
   }
   ```

## 在 Kinesis 中建立、說明和刪除串流
<a name="api-gateway-create-describe-delete-stream"></a>

 在 Kinesis 中建立、說明和刪除串流會分別進行下列 Kinesis REST API 請求：

```
POST /?Action=CreateStream HTTP/1.1
Host: kinesis.region.domain
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes

{
    "ShardCount": number,
    "StreamName": "string"
}
```

```
POST /?Action=DescribeStream HTTP/1.1
Host: kinesis.region.domain
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes

{
    "StreamName": "string"
}
```

```
POST /?Action=DeleteStream HTTP/1.1
Host: kinesis.region.domain
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes

{
    "StreamName":"string"
}
```

 我們可以建置 API 以接受所需的輸入做為方法請求的 JSON 承載，並將承載傳遞至整合請求。不過，若要提供方法與整合請求之間以及方法與整合回應之間的更多資料對應範例，我們會建立略為不同的 API。

 我們會對指定的 `GET` 資源公開 `POST`、`Delete` 和 `Stream` HTTP 方法。我們使用 `{stream-name}` 路徑變數做為串流資源的預留位置，並分別整合這些 API 方法與 Kinesis 的 `DescribeStream`、`CreateStream` 和 `DeleteStream` 動作。我們需要用戶端將其他輸入資料傳遞為方法請求的標頭、查詢參數或承載。我們提供對應範本將資料轉換為所需的整合請求承載。

**建立 \$1stream-name\$1 資源**

1. 選擇 **/streams** 資源，然後選擇**建立資源**。

1. 讓**代理資源**保持關閉。

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

1. 針對**資源名稱**，輸入 **\$1stream-name\$1**。

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

**設定和測試串流資源上的 GET 方法**

1. 選擇 **/\$1stream-name\$1** 資源，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **DescribeStream**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

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

1. 在**整合請求**區段中，新增下列 **URL 請求標頭參數**：

   ```
   Content-Type: 'x-amz-json-1.1'
   ```

   任務所遵循的程序與設定 `GET /streams` 方法的請求參數映射相同。

1. 新增下列內文對應範本，以將資料從 `GET /streams/{stream-name}` 方法請求對應至 `POST /?Action=DescribeStream` 整合請求：

   ```
   {
       "StreamName": "$input.params('stream-name')"
   }
   ```

   此對應範本會透過方法請求的 `DescribeStream` 路徑參數值，來產生 Kinesis 之 `stream-name` 動作所需的整合請求承載。

1. 若要測試在 Kinesis 中叫用 `DescribeStream` 動作的 `GET /stream/{stream-name}` 方法，請選擇**測試**索引標籤。

1. 針對**路徑**，在 **stream-name** 下，輸入現有 Kinesis 串流的名稱。

1. 選擇**測試**。如果測試成功，則會傳回承載與類似下列的 200 OK 回應：

   ```
   {
     "StreamDescription": {
       "HasMoreShards": false,
       "RetentionPeriodHours": 24,
       "Shards": [
         {
           "HashKeyRange": {
             "EndingHashKey": "68056473384187692692674921486353642290",
             "StartingHashKey": "0"
           },
           "SequenceNumberRange": {
             "StartingSequenceNumber": "49559266461454070523309915164834022007924120923395850242"
           },
           "ShardId": "shardId-000000000000"
         },
         ...
         {
           "HashKeyRange": {
             "EndingHashKey": "340282366920938463463374607431768211455",
             "StartingHashKey": "272225893536750770770699685945414569164"
           },
           "SequenceNumberRange": {
             "StartingSequenceNumber": "49559266461543273504104037657400164881014714369419771970"
           },
           "ShardId": "shardId-000000000004"
         }
       ],
       "StreamARN": "arn:aws:kinesis:us-east-1:12345678901:stream/myStream",
       "StreamName": "myStream",
       "StreamStatus": "ACTIVE"
     }
   }
   ```

    在您部署 API 之後，可以針對此 API 方法提出 REST 請求：

   ```
   GET https://your-api-id.execute-api.region.amazonaws.com/stage/streams/myStream HTTP/1.1
   Host: your-api-id.execute-api.region.amazonaws.com
   Content-Type: application/json
   Authorization: ...
   X-Amz-Date: 20160323T194451Z
   ```

**設定和測試串流資源上的 POST 方法**

1. 選擇 **/\$1stream-name\$1** 資源，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **CreateStream**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

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

1. 在**整合請求**區段中，新增下列 **URL 請求標頭參數**：

   ```
   Content-Type: 'x-amz-json-1.1'
   ```

   任務所遵循的程序與設定 `GET /streams` 方法的請求參數映射相同。

1.  新增下列內文對應範本，以將資料從 `POST /streams/{stream-name}` 方法請求對應至 `POST /?Action=CreateStream` 整合請求：

   ```
   {
       "ShardCount": #if($input.path('$.ShardCount') == '') 5 #else $input.path('$.ShardCount') #end,
       "StreamName": "$input.params('stream-name')"
   }
   ```

    如果用戶端未在方法請求承載中指定值，則在先前的對應範本中，我們將 `ShardCount` 設定為固定值 5。

1. 若要測試在 Kinesis 中叫用 `CreateStream` 動作的 `POST /stream/{stream-name}` 方法，請選擇**測試**索引標籤。

1. 針對**路徑**，在 **stream-name** 下，輸入新 Kinesis 串流的名稱。

1. 選擇**測試**。如果測試成功，則會傳回 200 OK 回應，而沒有資料。

    在您部署 API 之後，也可以對串流資源上的 POST 方法提出 REST API 請求，以在 Kinesis 中叫用 `CreateStream` 動作：

   ```
   POST https://your-api-id.execute-api.region.amazonaws.com/stage/streams/yourStream HTTP/1.1
   Host: your-api-id.execute-api.region.amazonaws.com
   Content-Type: application/json
   Authorization: ...
   X-Amz-Date: 20160323T194451Z
   
   { 
       "ShardCount": 5
   }
   ```

**設定和測試串流資源上的 DELETE 方法**

1. 選擇 **/\$1stream-name\$1** 資源，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **DeleteStream**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

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

1. 在**整合請求**區段中，新增下列 **URL 請求標頭參數**：

   ```
   Content-Type: 'x-amz-json-1.1'
   ```

   任務所遵循的程序與設定 `GET /streams` 方法的請求參數映射相同。

1.  新增下列內文對應範本，以將資料從 `DELETE /streams/{stream-name}` 方法請求對應至對應的 `POST /?Action=DeleteStream` 整合請求：

   ```
   {
       "StreamName": "$input.params('stream-name')"
   }
   ```

    此對應範本會從 `DELETE /streams/{stream-name}` 中由用戶端提供的 URL 路徑名稱，產生 `stream-name` 動作的所需輸入。

1. 若要測試在 Kinesis 中叫用 `DeleteStream` 動作的 `DELETE /stream/{stream-name}` 方法，請選擇**測試**索引標籤。

1. 針對**路徑**，在 **stream-name** 下，輸入現有 Kinesis 串流的名稱。

1. 選擇**測試**。如果測試成功，則會傳回 200 OK 回應，而沒有資料。

    在您部署 API 之後，也可以對串流資源上的 DELETE 方法提出下列 REST API 請求，以在 Kinesis 中呼叫 `DeleteStream` 動作：

   ```
   DELETE https://your-api-id.execute-api.region.amazonaws.com/stage/streams/yourStream HTTP/1.1
   Host: your-api-id.execute-api.region.amazonaws.com
   Content-Type: application/json
   Authorization: ...
   X-Amz-Date: 20160323T194451Z
   
   {}
   ```

## 取得 Kinesis 中串流的記錄，並將記錄新增至其中
<a name="api-gateway-get-and-add-records-to-stream"></a>

 在您於 Kinesis 中建立串流之後，可以將資料記錄新增至串流，並讀取串流中的資料。新增資料記錄包含在 Kinesis 中呼叫 [PutRecords](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html#API_PutRecords_Examples) 或 [PutRecord](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html#API_PutRecord_Examples) 動作。前者會新增多筆記錄，而後者將單一記錄新增至串流。

```
POST /?Action=PutRecords HTTP/1.1
Host: kinesis.region.domain
Authorization: AWS4-HMAC-SHA256 Credential=..., ...
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes

{
    "Records": [
        {
            "Data": blob,
            "ExplicitHashKey": "string",
            "PartitionKey": "string"
        }
    ],
    "StreamName": "string"
}
```

或

```
POST /?Action=PutRecord HTTP/1.1
Host: kinesis.region.domain
Authorization: AWS4-HMAC-SHA256 Credential=..., ...
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes

{
    "Data": blob,
    "ExplicitHashKey": "string",
    "PartitionKey": "string",
    "SequenceNumberForOrdering": "string",
    "StreamName": "string"
}
```

 在這裡，`StreamName` 識別要新增記錄的目標串流。`StreamName`、`Data` 和 `PartitionKey` 是必要輸入資料。在範例中，我們使用所有選用輸入資料的預設值，因此將不會在方法請求輸入中明確指定其值。

 讀取 Kinesis 數量中的資料以呼叫 [GetRecords](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html#API_GetRecords_Examples) 動作：

```
POST /?Action=GetRecords HTTP/1.1
Host: kinesis.region.domain
Authorization: AWS4-HMAC-SHA256 Credential=..., ...
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes

{
    "ShardIterator": "string",
    "Limit": number
}
```

在這裡，從中取得記錄的來源串流指定於所需 `ShardIterator` 值，如可取得碎片迭代運算的下列 Kinesis 動作所示：

```
POST /?Action=GetShardIterator HTTP/1.1
Host: kinesis.region.domain
Authorization: AWS4-HMAC-SHA256 Credential=..., ...
...
Content-Type: application/x-amz-json-1.1
Content-Length: PayloadSizeBytes
                
{
    "ShardId": "string",
    "ShardIteratorType": "string",
    "StartingSequenceNumber": "string",
    "StreamName": "string"
}
```

 針對 `GetRecords` 和 `PutRecords` 動作，我們分別在附加至具名串流資源 (`GET`) 的 `PUT` 資源上公開 `/records` 和 `/{stream-name}` 方法。同樣地，我們將 `PutRecord` 動作公開為 `PUT` 資源上的 `/record` 方法。

 因為 `GetRecords` 動作將呼叫 `ShardIterator` helper 動作所取得的 `GetShardIterator` 值採用為輸入，所以我們在 `GET` 資源上公開 `ShardIterator` helper 方法 (`/sharditerator`)。

**建立 /record、/records 和 /sharditerator 資源**

1. 選擇 **/\$1stream-name\$1** 資源，然後選擇**建立資源**。

1. 讓**代理資源**保持關閉。

1. 針對**資源路徑**，選取 `/{stream-name}`。

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

1. 讓 **CORS (跨來源資源分享)** 保持關閉。

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

1. 重複前面的步驟，以建立 **/records** 和 **/sharditerator** 資源。最終 API 應如下所示：

      
![\[建立 API 的 Records:GET|PUT|PUT|GET 方法。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/api-gateway-kinesis-proxy-setup-streams-stream-record-method-new-console.png)

 下列四個程序說明如何設定每種方法、如何將資料從方法請求對應至整合請求，以及如何測試方法。

**設定和測試 `PUT /streams/{stream-name}/record` 方法以在 Kinesis 中叫用 `PutRecord`：**

1. 選擇 **/record**，然後選擇**建立方法**。

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **PutRecord**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

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

1. 在**整合請求**區段中，新增下列 **URL 請求標頭參數**：

   ```
   Content-Type: 'x-amz-json-1.1'
   ```

   任務所遵循的程序與設定 `GET /streams` 方法的請求參數映射相同。

1.  新增下列內文對應範本，以將資料從 `PUT /streams/{stream-name}/record` 方法請求對應至對應的 `POST /?Action=PutRecord` 整合請求：

   ```
   {
       "StreamName": "$input.params('stream-name')",
       "Data": "$util.base64Encode($input.json('$.Data'))",
       "PartitionKey": "$input.path('$.PartitionKey')"
   }
   ```

    此對應範本假設方法請求承載的格式如下：

   ```
   {
      "Data": "some data",
      "PartitionKey": "some key"
   }
   ```

   此資料可以透過下列 JSON 結構描述建立模型：

   ```
   {
     "$schema": "http://json-schema.org/draft-04/schema#",
     "title": "PutRecord proxy single-record payload",
     "type": "object",
     "properties": {
         "Data": { "type": "string" },
         "PartitionKey": { "type": "string" }
     }
   }
   ```

    您可以建立模型來包含此結構描述，並使用此模型來促進產生對應範本。不過，您可以產生對應範本，而不使用任何模型。

1.  若要測試 `PUT /streams/{stream-name}/record` 方法，請將 `stream-name` 路徑變數設定為現有串流的名稱，並提供所需格式的承載，然後提交方法請求。成功結果是承載格式如下的 `200 OK `回應：

   ```
   {
     "SequenceNumber": "49559409944537880850133345460169886593573102115167928386",
     "ShardId": "shardId-000000000004"
   }
   ```

**設定和測試 `PUT /streams/{stream-name}/records` 方法以在 Kinesis 中叫用 `PutRecords`**

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **PutRecords**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

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

1. 在**整合請求**區段中，新增下列 **URL 請求標頭參數**：

   ```
   Content-Type: 'x-amz-json-1.1'
   ```

   任務所遵循的程序與設定 `GET /streams` 方法的請求參數映射相同。

1.  新增下列對應範本，以將資料從 `PUT /streams/{stream-name}/records` 方法請求對應至對應的 `POST /?Action=PutRecords` 整合請求：

   ```
   {
       "StreamName": "$input.params('stream-name')",
       "Records": [
          #foreach($elem in $input.path('$.records'))
             {
               "Data": "$util.base64Encode($elem.data)",
               "PartitionKey": "$elem.partition-key"
             }#if($foreach.hasNext),#end
           #end
       ]
   }
   ```

   此對應範本假設方法請求承載可以透過下列 JSON 結構描述建立模型：

   ```
   {
     "$schema": "http://json-schema.org/draft-04/schema#",
     "title": "PutRecords proxy payload data",
     "type": "object",
     "properties": {
       "records": {
         "type": "array",
         "items": {
           "type": "object",
           "properties": {
             "data": { "type": "string" },
             "partition-key": { "type": "string" }
           }
         }
       }
     }
   }
   ```

    您可以建立模型來包含此結構描述，並使用此模型來促進產生對應範本。不過，您可以產生對應範本，而不使用任何模型。

   在本教學中，我們使用兩個略為不同的承載格式來說明 API 開發人員可以選擇向用戶端公開後端資料格式，或向用戶端隱藏它。其中一種格式適用於 `PUT /streams/{stream-name}/records` 方法 (上方)。另一種格式用於 `PUT /streams/{stream-name}/record` 方法 (在先前的程序中)。在生產環境中，您應該保持這兩種格式一致。

1. 

    若要測試 `PUT /streams/{stream-name}/records` 方法，請將 `stream-name` 路徑變數設定為現有串流，並提供下列承載，然後提交方法請求。

   ```
   {
       "records": [
           {
               "data": "some data",
               "partition-key": "some key"
           },
           {
               "data": "some other data",
               "partition-key": "some key"
           }
       ]
   }
   ```

   成功結果是承載與下列輸出類似的 200 OK 回應：

   ```
   {
     "FailedRecordCount": 0,
     "Records": [
       {
         "SequenceNumber": "49559409944537880850133345460167468741933742152373764162",
         "ShardId": "shardId-000000000004"
       },
       {
         "SequenceNumber": "49559409944537880850133345460168677667753356781548470338",
         "ShardId": "shardId-000000000004"
       }
     ]
   }
   ```

**設定和測試 `GET /streams/{stream-name}/sharditerator` 方法以在 Kinesis 中叫用 `GetShardIterator`**

`GET /streams/{stream-name}/sharditerator` 方法是 helper 方法，可先獲得必要碎片迭代運算，再呼叫 `GET /streams/{stream-name}/records` 方法。

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **GetShardIterator**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

1. 選擇 **URL 查詢字串參數**。

   `GetShardIterator` 動作需要 ShardId 值的輸入。若要傳遞用戶端提供的 `ShardId` 值，我們將 `shard-id` 查詢參數新增至方法請求，如下列步驟所示。

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

1. 對於**名稱**，輸入 **shard-id**。

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

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

1. 在**整合請求**區段中，新增下列對應範本，以從方法請求的 `shard-id` 和 `stream-name` 參數產生 `GetShardIterator` 動作所需的輸入 (`ShardId` 和 `StreamName`)。此外，對應範本也會將 `ShardIteratorType` 設定為 `TRIM_HORIZON` 做為預設值。

   ```
   {
       "ShardId": "$input.params('shard-id')",
       "ShardIteratorType": "TRIM_HORIZON",
       "StreamName": "$input.params('stream-name')"
   }
   ```

1.  使用 API Gateway 主控台中的 **Test (測試)** 選項，輸入現有串流名稱作為 `stream-name` **Path (路徑)** 變數值，並將 `shard-id` **Query string (查詢字串)** 設定為現有 `ShardId` 值 (例如，`shard-000000000004`)，然後選擇 **Test (測試)**。

    成功回應承載與下列輸出類似：

   ```
   {
     "ShardIterator": "AAAAAAAAAAFYVN3VlFy..."
   }
   ```

   記下 `ShardIterator` 值。您需要有它才能從串流取得記錄。

**設定和測試 `GET /streams/{stream-name}/records` 方法，在 Kinesis 中叫用 `GetRecords` 動作**

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

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

1. 針對**整合類型**，選取 **AWS 服務**。

1. 針對 **AWS 區域**，選取您建立 Kinesis 串流 AWS 區域 的 。

1. 針對 **AWS 服務**，選取 **Kinesis**。

1. 讓 **AWS 子網域**保持空白。

1. 針對 **HTTP 方法**，請選擇 **POST**。

1. 針對**動作類型**，選擇**使用動作名稱**。

1. 針對**動作名稱**，輸入 **GetRecords**。

1. 針對**執行角色**，輸入執行角色的 ARN。

1. 保留**內容處理**之**傳遞**的預設值。

1. 選擇 **HTTP 請求標頭**。

    `GetRecords` 動作需要 `ShardIterator` 值的輸入。若要傳遞用戶端提供的 `ShardIterator` 值，我們會將 `Shard-Iterator` 標頭參數新增至方法請求。

1. 選擇**新增標頭**。

1. 對於**名稱**，輸入 **Shard-Iterator**。

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

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

1.  在**整合請求**區段中，新增下列內文對應範本，以將 `Shard-Iterator` 標頭參數值對應至 Kinesis 中 `GetRecords` 動作之 JSON 承載的 `ShardIterator` 屬性值。

   ```
   {
       "ShardIterator": "$input.params('Shard-Iterator')"
   }
   ```

1.  使用 API Gateway 主控台中的**測試**選項，輸入現有串流名稱做為 `stream-name` **路徑**變數值，並將 `Shard-Iterator` **標頭**設定為取自 `ShardIterator` 方法 (上方) 測試回合的 `GET /streams/{stream-name}/sharditerator` 值，然後選擇**測試**。

    成功回應承載與下列輸出類似：

   ```
   {
     "MillisBehindLatest": 0,
     "NextShardIterator": "AAAAAAAAAAF...",
     "Records": [ ... ]
   }
   ```

# 做為 Kinesis 代理之範例 API 的 OpenAPI 定義
<a name="api-as-kinesis-proxy-export-swagger-with-extensions"></a>

以下是用於本教學課程中做為 Kinesis 代理之範例 API 的 OpenAPI 定義。

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

```
{
  "openapi": "3.0.0",
  "info": {
    "title": "KinesisProxy",
    "version": "2016-03-31T18:25:32Z"
  },
  "paths": {
    "/streams/{stream-name}/sharditerator": {
      "get": {
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "shard-id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/GetShardIterator",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"ShardId\": \"$input.params('shard-id')\",\n    \"ShardIteratorType\": \"TRIM_HORIZON\",\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}/records": {
      "get": {
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Shard-Iterator",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/GetRecords",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"ShardIterator\": \"$input.params('Shard-Iterator')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      },
      "put": {
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutRecordsMethodRequestPayload"
              }
            },
            "application/x-amz-json-1.1": {
              "schema": {
                "$ref": "#/components/schemas/PutRecordsMethodRequestPayload"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/PutRecords",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\",\n    \"Records\": [\n          {\n            \"Data\": \"$util.base64Encode($elem.data)\",\n            \"PartitionKey\": \"$elem.partition-key\"\n          }#if($foreach.hasNext),#end\n    ]\n}",
            "application/x-amz-json-1.1": "{\n  \"StreamName\": \"$input.params('stream-name')\",\n  \"records\" : [\n    {\n        \"Data\" : \"$elem.data\",\n        \"PartitionKey\" : \"$elem.partition-key\"\n    }#if($foreach.hasNext),#end\n  ]\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}": {
      "get": {
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/DescribeStream",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      },
      "post": {
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/CreateStream",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"ShardCount\": 5,\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      },
      "delete": {
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Content-Type": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          },
          "400": {
            "description": "400 response",
            "headers": {
              "Content-Type": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {}
          },
          "500": {
            "description": "500 response",
            "headers": {
              "Content-Type": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {}
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/DeleteStream",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            },
            "5\\d{2}": {
              "statusCode": "500",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}/record": {
      "put": {
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/PutRecord",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\",\n    \"Data\": \"$util.base64Encode($input.json('$.Data'))\",\n    \"PartitionKey\": \"$input.path('$.PartitionKey')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams": {
      "get": {
        "responses": {
          "200": {
            "description": "200 response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empty"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/ListStreams",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Empty": {
        "type": "object"
      },
      "PutRecordsMethodRequestPayload": {
        "type": "object",
        "properties": {
          "records": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "data": {
                  "type": "string"
                },
                "partition-key": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
```

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

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-03-31T18:25:32Z",
    "title": "KinesisProxy"
  },
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/streams": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/ListStreams",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/DescribeStream",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      },
      "post": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/CreateStream",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"ShardCount\": 5,\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      },
      "delete": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "400": {
            "description": "400 response",
            "headers": {
              "Content-Type": {
                "type": "string"
              }
            }
          },
          "500": {
            "description": "500 response",
            "headers": {
              "Content-Type": {
                "type": "string"
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/DeleteStream",
          "responses": {
            "4\\d{2}": {
              "statusCode": "400",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            },
            "5\\d{2}": {
              "statusCode": "500",
              "responseParameters": {
                "method.response.header.Content-Type": "integration.response.header.Content-Type"
              }
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}/record": {
      "put": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/PutRecord",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\",\n    \"Data\": \"$util.base64Encode($input.json('$.Data'))\",\n    \"PartitionKey\": \"$input.path('$.PartitionKey')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}/records": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "Shard-Iterator",
            "in": "header",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/GetRecords",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"ShardIterator\": \"$input.params('Shard-Iterator')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      },
      "put": {
        "consumes": [
          "application/json",
          "application/x-amz-json-1.1"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": false,
            "type": "string"
          },
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "in": "body",
            "name": "PutRecordsMethodRequestPayload",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PutRecordsMethodRequestPayload"
            }
          },
          {
            "in": "body",
            "name": "PutRecordsMethodRequestPayload",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PutRecordsMethodRequestPayload"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/PutRecords",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"StreamName\": \"$input.params('stream-name')\",\n    \"Records\": [\n          {\n            \"Data\": \"$util.base64Encode($elem.data)\",\n            \"PartitionKey\": \"$elem.partition-key\"\n          }#if($foreach.hasNext),#end\n    ]\n}",
            "application/x-amz-json-1.1": "{\n  \"StreamName\": \"$input.params('stream-name')\",\n  \"records\" : [\n    {\n        \"Data\" : \"$elem.data\",\n        \"PartitionKey\" : \"$elem.partition-key\"\n    }#if($foreach.hasNext),#end\n  ]\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    },
    "/streams/{stream-name}/sharditerator": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "stream-name",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "shard-id",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "aws",
          "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole",
          "uri": "arn:aws:apigateway:us-east-1:kinesis:action/GetShardIterator",
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.header.Content-Type": "'application/x-amz-json-1.1'"
          },
          "requestTemplates": {
            "application/json": "{\n    \"ShardId\": \"$input.params('shard-id')\",\n    \"ShardIteratorType\": \"TRIM_HORIZON\",\n    \"StreamName\": \"$input.params('stream-name')\"\n}"
          },
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST"
        }
      }
    }
  },
  "definitions": {
    "Empty": {
      "type": "object"
    },
    "PutRecordsMethodRequestPayload": {
      "type": "object",
      "properties": {
        "records": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "data": {
                "type": "string"
              },
              "partition-key": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
```

------

# 教學課程：使用 AWS SDKs或 建立 REST API AWS CLI
<a name="api-gateway-create-api-cli-sdk"></a>

使用下列教學課程建立支援 `GET /pets` 和 `GET /pets/{petId}` 方法的 PetStore API。該方法會與 HTTP 端點整合。您可以使用適用於 JavaScript 的 AWS SDK、適用於 Python 的 SDK (Boto3) 或 來遵循本教學課程 AWS CLI。您可以使用下列函數或命令來設定 API：

------
#### [ JavaScript v3 ]
+ [ CreateRestApiCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/CreateRestApiCommand/)
+ [ CreateResourceCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/CreateResourceCommand/)
+ [ PutMethodCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/PutMethodCommand/)
+ [ PutMethodResponseCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/PutMethodResponseCommand/)
+ [ PutIntegrationCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/PutIntegrationCommand/)
+ [ PutIntegrationResponseCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/PutIntegrationResponseCommand/)
+ [ CreateDeploymentCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/api-gateway/command/CreateDeploymentCommand/)

------
#### [ Python ]
+ [ create\$1rest\$1api](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/create_rest_api.html)
+ [ create\$1resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/create_resource.html)
+ [ put\$1method](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/put_method.html)
+ [ put\$1method\$1response](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/put_method_response.html)
+ [ put\$1integration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/put_integration.html)
+ [ put\$1integration\$1response](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/put_integration_response.html)
+ [ create\$1deployment](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway/client/create_deployment.html)

------
#### [ AWS CLI ]
+ [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html)
+  [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 
+  [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 
+  [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) 
+  [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 
+  [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) 
+  [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 

------

如需適用於 JavaScript 的 AWS SDK v3 的詳細資訊，請參閱[什麼是適用於 JavaScript 的 AWS SDK？](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html)。如需 SDK for Python (Boto3) 的詳細資訊，請參閱 [適用於 Python (Boto3) 的 AWS SDK](https://docs.aws.amazon.com/pythonsdk)。如需 的詳細資訊 AWS CLI，請參閱[什麼是 AWS CLI？](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)

## 設定邊緣最佳化的 PetStore API
<a name="api-gateway-create-api-cli-sdk-tutorial"></a>

在本教學課程中，範例命令會使用值 ID 的預留位置值，例如 API ID 和資源 ID。完成教學課程時，請將這些值取代為您自己的值。

**使用 AWS SDKs 設定邊緣最佳化 PetStore API**

1. 使用以下程式碼建立 `RestApi` 實體：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient, CreateRestApiCommand} from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new CreateRestApiCommand({
       name: "Simple PetStore (JavaScript v3 SDK)",
       description: "Demo API created using the AWS SDK for JavaScript v3",
       version: "0.00.001",
       binaryMediaTypes: [
       '*']
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.error(Couldn't create API:\n", err)
   }
   })();
   ```

   成功的呼叫會在如下所示的輸出中，傳回您的 API ID 和 API 的根資源 ID：

   ```
   {
     id: 'abc1234',
     name: 'PetStore (JavaScript v3 SDK)',
     description: 'Demo API created using the AWS SDK for node.js',
     createdDate: 2017-09-05T19:32:35.000Z,
     version: '0.00.001',
     rootResourceId: 'efg567'
     binaryMediaTypes: [ '*' ] 
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.create_rest_api(
           name='Simple PetStore (Python SDK)',
           description='Demo API created using the AWS SDK for Python',
           version='0.00.001',
           binaryMediaTypes=[
               '*'
           ]
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Couldn't create REST API %s.", error)
       raise
   attribute=["id","name","description","createdDate","version","binaryMediaTypes","apiKeySource","endpointConfiguration","disableExecuteApiEndpoint","rootResourceId"]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會在如下所示的輸出中，傳回您的 API ID 和 API 的根資源 ID：

   ```
   {'id': 'abc1234', 'name': 'Simple PetStore (Python SDK)', 'description': 'Demo API created using the AWS SDK for Python', 'createdDate': datetime.datetime(2024, 4, 3, 14, 31, 39, tzinfo=tzlocal()), 'version': '0.00.001', 'binaryMediaTypes': ['*'], 'apiKeySource': 'HEADER', 'endpointConfiguration': {'types': ['EDGE']}, 'disableExecuteApiEndpoint': False, 'rootResourceId': 'efg567'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway create-rest-api --name 'Simple PetStore (AWS CLI)' --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "id": "abcd1234", 
       "name": "Simple PetStore (AWS CLI)", 
       "createdDate": "2022-12-15T08:07:04-08:00",
       "apiKeySource": "HEADER",
       "endpointConfiguration": {
           "types": [
               "EDGE"
           ]
       },
       "disableExecuteApiEndpoint": false,
       "rootResourceId": "efg567"
   }
   ```

------

   您建立的 API 具有 `abcd1234` 的 API ID 和 `efg567` 的根資源 ID。您可以在 API 的設定中使用這些值。

1. 若要在根的下方附加子資源，請將 `RootResourceId` 指定為 `parentId` 屬性值。使用下列範例為您的 API 建立 `/pets` 資源：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  CreateResourceCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new CreateResourceCommand({
       restApiId: 'abcd1234',
       parentId: 'efg567',
       pathPart: 'pets'
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The '/pets' resource setup failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下之輸出中的資源相關資訊：

   ```
   {
       "path": "/pets", 
       "pathPart": "pets", 
       "id": "aaa111", 
       "parentId": "efg567'"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.create_resource(
           restApiId='abcd1234',
           parentId='efg567',
           pathPart='pets'
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("The '/pets' resource setup failed: %s.", error)
       raise
   attribute=["id","parentId", "pathPart", "path",]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下之輸出中的資源相關資訊：

   ```
   {'id': 'aaa111', 'parentId': 'efg567', 'pathPart': 'pets', 'path': '/pets'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway create-resource --rest-api-id abcd1234 \
     --region us-west-2 \
     --parent-id efg567 \
     --path-part pets
   ```

   以下是此命令的輸出：

   ```
   {
       "id": "aaa111", 
       "parentId": "efg567",
       "pathPart": "pets",
       "path": "/pets"
   }
   ```

------

   您建立的 `/pets` 資源具有 `aaa111` 的資源 ID。您可以在 API 的設定中使用此值。

1. 接著，您會在 `/pets` 資源下附加子資源。此資源 `/{petId}` 具有 `{petId}` 的路徑參數。若要將路徑部分設為路徑參數，請將它括在一對大括號中 (`{ }`)。使用下列範例為您的 API 建立 `/pets/{petId}` 資源：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  CreateResourceCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new CreateResourceCommand({
       restApiId: 'abcd1234',
       parentId: 'aaa111',
       pathPart: '{petId}'
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The '/pets/{petId}' resource setup failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下之輸出中的資源相關資訊：

   ```
   {
       "path": "/pets/{petId}", 
       "pathPart": "{petId}", 
       "id": "bbb222", 
       "parentId": "aaa111'"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.create_resource(
           restApiId='abcd1234',
           parentId='aaa111',
           pathPart='{petId}'
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("The '/pets/{petId}' resource setup failed: %s.", error)
       raise
   attribute=["id","parentId", "pathPart", "path",]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下之輸出中的資源相關資訊：

   ```
   {'id': 'bbb222', 'parentId': 'aaa111', 'pathPart': '{petId}', 'path': '/pets/{petId}'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway create-resource --rest-api-id abcd1234 \
     --region us-west-2 \
     --parent-id aaa111 \
     --path-part '{petId}'
   ```

   以下是此命令的輸出：

   ```
   {
       "id": "bbb222",
       "parentId": "aaa111",
       "path": "/pets/{petId}", 
       "pathPart": "{petId}"
   }
   ```

------

   您建立的 `/pets/{petId}` 資源具有 `bbb222` 的資源 ID。您可以在 API 的設定中使用此值。

1. 在下列兩個步驟中，您將 HTTP 方法新增至您的資源。在本教學課程中，您將方法設定為具有開放存取權，方法是將 `authorization-type` 設定為 `NONE`。若只要允許已驗證的使用者呼叫方法，您可以使用 IAM 角色與政策、Lambda 授權方 (先前稱為自訂授權方) 或 Amazon Cognito 使用者集區。如需詳細資訊，請參閱[在 API Gateway 中控制和管理對 REST API 的存取](apigateway-control-access-to-api.md)。

   使用下列範例在 `/pets` 資源上新增 `GET` HTTP 方法：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutMethodCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutMethodCommand({
       restApiId: 'abcd1234',
       resourceId: 'aaa111',
       httpMethod: 'GET',
       authorizationType: 'NONE'
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The 'GET /pets' method setup failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "GET", 
       "authorizationType": "NONE"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_method(
           restApiId='abcd1234',
           resourceId='aaa111',
           httpMethod='GET',
           authorizationType='NONE'
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("The 'GET /pets' method setup failed: %s", error)
       raise
   attribute=["httpMethod","authorizationType","apiKeyRequired"]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'httpMethod': 'GET', 'authorizationType': 'NONE', 'apiKeyRequired': False}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-method --rest-api-id abcd1234 \
     --resource-id aaa111 \
     --http-method GET \
     --authorization-type "NONE" \
     --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "httpMethod": "GET", 
       "authorizationType": "NONE",
       "apiKeyRequired": false
   }
   ```

------

1. 使用下列範例在 `/pets/{petId}` 資源上新增 `GET` HTTP 方法，並設定 `requestParameters` 屬性將用戶端提供的 `petId` 值傳遞至後端：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutMethodCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutMethodCommand({
       restApiId: 'abcd1234',
       resourceId: 'bbb222',
       httpMethod: 'GET',
       authorizationType: 'NONE'
       requestParameters: {
           "method.request.path.petId" : true
       }
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The 'GET /pets/{petId}' method setup failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "GET", 
       "authorizationType": "NONE",
       "requestParameters": {
          "method.request.path.petId": true
       }
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_method(
           restApiId='abcd1234',
           resourceId='bbb222',
           httpMethod='GET',
           authorizationType='NONE',
           requestParameters={
               "method.request.path.petId": True
           }
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("The 'GET /pets/{petId}' method setup failed: %s", error)
       raise
   attribute=["httpMethod","authorizationType","apiKeyRequired", "requestParameters" ]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'httpMethod': 'GET', 'authorizationType': 'NONE', 'apiKeyRequired': False, 'requestParameters': {'method.request.path.petId': True}}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-method --rest-api-id abcd1234 \
     --resource-id bbb222 --http-method GET \
     --authorization-type "NONE" \
     --region us-west-2 \
     --request-parameters method.request.path.petId=true
   ```

   以下是此命令的輸出：

   ```
   {
       "httpMethod": "GET", 
       "authorizationType": "NONE", 
       "apiKeyRequired": false, 
       "requestParameters": {
           "method.request.path.petId": true
       }
   }
   ```

------

1. 針對 `GET /pets` 方法回應，使用下列範例新增 200 OK 方法：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutMethodResponseCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutMethodResponseCommand({
       restApiId: 'abcd1234',
       resourceId: 'aaa111',
       httpMethod: 'GET',
       statusCode: '200'
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("Set up the 200 OK response for the 'GET /pets' method failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "statusCode": "200"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_method_response(
           restApiId='abcd1234',
           resourceId='aaa111',
           httpMethod='GET',
           statusCode='200'
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Set up the 200 OK response for the 'GET /pets' method failed %s.", error)
       raise
   attribute=["statusCode"]
   filtered_result ={key:result[key] for key in attribute}
   logger.info(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'statusCode': '200'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-method-response --rest-api-id abcd1234 \ 
     --resource-id aaa111 --http-method GET \
     --status-code 200  --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "statusCode": "200"
   }
   ```

------

1. 針對 `GET /pets/{petId}` 方法回應，使用下列範例新增 200 OK 方法：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutMethodResponseCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutMethodResponseCommand({
       restApiId: 'abcd1234',
       resourceId: 'bbb222',
       httpMethod: 'GET',
       statusCode: '200'
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("Set up the 200 OK response for the 'GET /pets/{petId}' method failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "statusCode": "200"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_method_response(
           restApiId='abcd1234',
           resourceId='bbb222',
           httpMethod='GET',
           statusCode='200'
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Set up the 200 OK response for the 'GET /pets/{petId}' method failed %s.", error)
       raise
   attribute=["statusCode"]
   filtered_result ={key:result[key] for key in attribute}
   logger.info(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'statusCode': '200'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-method-response --rest-api-id abcd1234 \ 
     --resource-id bbb222 --http-method GET \
     --status-code 200  --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "statusCode": "200"
   }
   ```

------

1. 使用下列範例設定 `GET /pets` 方法與 HTTP 端點的整合。HTTP 端點為 `http://petstore-demo-endpoint.execute-api.com/petstore/pets`。

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutIntegrationCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutIntegrationCommand({
       restApiId: 'abcd1234',
       resourceId: 'aaa111',
       httpMethod: 'GET',
       type: 'HTTP',
       integrationHttpMethod: 'GET',
       uri: 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("Set up the integration of the 'GET /pets' method of the API failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "httpMethod": "GET", 
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "type": "HTTP", 
       "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/pets", 
       "cacheNamespace": "ccc333"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_integration(
           restApiId='abcd1234',
           resourceId='aaa111',
           httpMethod='GET',
           type='HTTP',
           integrationHttpMethod='GET',
           uri='http://petstore-demo-endpoint.execute-api.com/petstore/pets'
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Set up the integration of the 'GET /' method of the API failed %s.", error)
       raise
   attribute=["httpMethod","passthroughBehavior","cacheKeyParameters", "type", "uri", "cacheNamespace"]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'httpMethod': 'GET', 'passthroughBehavior': 'WHEN_NO_MATCH', 'cacheKeyParameters': [], 'type': 'HTTP', 'uri': 'http://petstore-demo-endpoint.execute-api.com/petstore/pets', 'cacheNamespace': 'ccc333'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-integration --rest-api-id abcd1234 \
     --resource-id aaa111 --http-method GET --type HTTP \
     --integration-http-method GET \
     --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets' \
     --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "type": "HTTP",
       "httpMethod": "GET",
       "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
       "connectionType": "INTERNET",
       "passthroughBehavior": "WHEN_NO_MATCH",
       "timeoutInMillis": 29000,
       "cacheNamespace": "6sxz2j",
       "cacheKeyParameters": []
   }
   ```

------

1. 使用下列範例設定 `GET /pets/{petId}` 方法與 HTTP 端點的整合。HTTP 端點為 `http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}`。在此步驟中，您將 `petId` 路徑參數映射至 `id` 的端點路徑參數。

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutIntegrationCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutIntegrationCommand({
       restApiId: 'abcd1234',
       resourceId: 'bbb222',
       httpMethod: 'GET',
       type: 'HTTP',
       integrationHttpMethod: 'GET',
       uri: 'http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}'
       requestParameters: {
           "integration.request.path.id": "method.request.path.petId"
        }
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("Set up the integration of the 'GET /pets/{petId}' method of the API failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "httpMethod": "GET", 
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "type": "HTTP", 
       "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}", 
       "cacheNamespace": "ddd444",
       "requestParameters": {
          "integration.request.path.id": "method.request.path.petId"
       }
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_integration(
           restApiId='ieps9b05sf',
           resourceId='t8zeb4',
           httpMethod='GET',
           type='HTTP',
           integrationHttpMethod='GET',
           uri='http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}',
           requestParameters={
               "integration.request.path.id": "method.request.path.petId"
           }
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Set up the integration of the 'GET /pets/{petId}' method of the API failed %s.", error)
       raise
   attribute=["httpMethod","passthroughBehavior","cacheKeyParameters", "type", "uri", "cacheNamespace", "requestParameters"]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'httpMethod': 'GET', 'passthroughBehavior': 'WHEN_NO_MATCH', 'cacheKeyParameters': [], 'type': 'HTTP', 'uri': 'http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}', 'cacheNamespace': 'ddd444', 'requestParameters': {'integration.request.path.id': 'method.request.path.petId'}}}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-integration --rest-api-id abcd1234 \
     --resource-id bbb222 --http-method GET --type HTTP \
     --integration-http-method GET \
     --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}' \ 
     --request-parameters '{"integration.request.path.id":"method.request.path.petId"}' \
     --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "type": "HTTP",
       "httpMethod": "GET",
       "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}",
       "connectionType": "INTERNET",
       "requestParameters": {
           "integration.request.path.id": "method.request.path.petId"
       },
       "passthroughBehavior": "WHEN_NO_MATCH",
       "timeoutInMillis": 29000,
       "cacheNamespace": "rjkmth",
       "cacheKeyParameters": []
   }
   ```

------

1. 使用下列範例新增對於 `GET /pets` 整合的整合回應：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutIntegrationResponseCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutIntegrationResponseCommand({
       restApiId: 'abcd1234',
       resourceId: 'aaa111',
       httpMethod: 'GET',
       statusCode: '200',
       selectionPattern: ''
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The 'GET /pets' method integration response setup failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "selectionPattern": "", 
       "statusCode": "200"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_integration_response(
           restApiId='abcd1234',
           resourceId='aaa111',
           httpMethod='GET',
           statusCode='200',
           selectionPattern='',
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Set up the integration response of the 'GET /pets' method of the API failed: %s", error)
       raise
   attribute=["selectionPattern","statusCode"]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'selectionPattern': "", 'statusCode': '200'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-integration-response --rest-api-id abcd1234 \
     --resource-id aaa111 --http-method GET \
     --status-code 200 --selection-pattern ""  \
     --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "statusCode": "200",
       "selectionPattern": "" 
   }
   ```

------

1. 使用下列範例新增對於 `GET /pets/{petId}` 整合的整合回應：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  PutIntegrationResponseCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new PutIntegrationResponseCommand({
       restApiId: 'abcd1234',
       resourceId: 'bbb222',
       httpMethod: 'GET',
       statusCode: '200',
       selectionPattern: ''
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The 'GET /pets/{petId}' method integration response setup failed:\n", err)
   }
   })();
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {
       "selectionPattern": "", 
       "statusCode": "200"
   }
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.put_integration_response(
           restApiId='abcd1234',
           resourceId='bbb222',
           httpMethod='GET',
           statusCode='200',
           selectionPattern='',
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Set up the integration response of the 'GET /pets/{petId}' method of the API failed: %s", error)
       raise
   attribute=["selectionPattern","statusCode"]
   filtered_result ={key:result[key] for key in attribute}
   print(filtered_result)
   ```

   成功的呼叫會傳回如下的輸出：

   ```
   {'selectionPattern': "", 'statusCode': '200'}
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway put-integration-response --rest-api-id abcd1234 \
     --resource-id bbb222 --http-method GET 
     --status-code 200 --selection-pattern ""  
     --region us-west-2
   ```

   以下是此命令的輸出：

   ```
   {
       "statusCode": "200",
       "selectionPattern": "" 
   }
   ```

------

   建立整合回應後，您的 API 可以在 PetStore 網站上查詢可用的寵物，並檢視指定識別碼的個別寵物。在客戶呼叫您的 API 之前，您必須先部署 API。建議您在部署 API 之前先進行測試。

1. 使用下列範例測試 `GET /pets` 方法：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  TestInvokeMethodCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new TestInvokeMethodCommand({
       restApiId: 'abcd1234',
       resourceId: 'aaa111',
       httpMethod: 'GET',
       pathWithQueryString: '/',
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The test on 'GET /pets' method failed:\n", err)
   }
   })();
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.test_invoke_method(
           restApiId='abcd1234',
           resourceId='aaa111',
           httpMethod='GET',
           pathWithQueryString='/',
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Test invoke method on 'GET /pets' failed: %s", error)
       raise
   print(result)
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway test-invoke-method --rest-api-id abcd1234 /
     --resource-id aaa111 /
     --http-method GET /
     --path-with-query-string '/'
   ```

------

1. 使用下列範例且 `petId` 為 3 來測試 `GET /pets/{petId}` 方法：

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  TestInvokeMethodCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new TestInvokeMethodCommand({
       restApiId: 'abcd1234',
       resourceId: 'bbb222',
       httpMethod: 'GET',
       pathWithQueryString: '/pets/3',
   });
   try {
       const results = await apig.send(command)
       console.log(results)
   } catch (err) {
       console.log("The test on 'GET /pets/{petId}' method failed:\n", err)
   }
   })();
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.test_invoke_method(
           restApiId='abcd1234',
           resourceId='bbb222',
           httpMethod='GET',
           pathWithQueryString='/pets/3',
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Test invoke method on 'GET /pets/{petId}' failed: %s", error)
       raise
   print(result)
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway test-invoke-method --rest-api-id abcd1234 /
     --resource-id bbb222 /
     --http-method GET /
     --path-with-query-string '/pets/3'
   ```

------

   成功測試 API 後，您可以將其部署至階段。

1. 使用下列範例將 API 部署至名為 `test` 的階段。當您將 API 部署至階段時，API 呼叫者就能調用您的 API。

------
#### [ JavaScript v3 ]

   ```
   import {APIGatewayClient,  CreateDeploymentCommand } from "@aws-sdk/client-api-gateway";
   (async function (){
   const apig = new APIGatewayClient({region:"us-east-1"});
   const command = new CreateDeploymentCommand({
       restApiId: 'abcd1234',
       stageName: 'test',
       stageDescription: 'test deployment'
   });
   try {
       const results = await apig.send(command)
       console.log("Deploying API succeeded\n", results)
   } catch (err) {
       console.log("Deploying API failed:\n", err)
   }
   })();
   ```

------
#### [ Python ]

   ```
   import botocore
   import boto3
   import logging
   
   logger = logging.getLogger()
   apig = boto3.client('apigateway')
   
   try:
       result = apig.create_deployment(
           restApiId='ieps9b05sf',
           stageName='test',
           stageDescription='my test stage',
       )
   except botocore.exceptions.ClientError as error:
       logger.exception("Error deploying stage  %s.", error)
       raise
   print('Deploying API succeeded')
   print(result)
   ```

------
#### [ AWS CLI ]

   ```
   aws apigateway create-deployment --rest-api-id abcd1234 \ 
     --region us-west-2 \
     --stage-name test \
     --stage-description 'Test stage' \
     --description 'First deployment'
   ```

   以下是此命令的輸出：

   ```
   {
       "id": "ab1c1d",
       "description": "First deployment",
       "createdDate": "2022-12-15T08:44:13-08:00"
   }
   ```

------

   現在客戶可以呼叫您的 API。您可以在瀏覽器中輸入 `https://abcd1234.execute-api.us-west-2.amazonaws.com/test/pets` URL 來測試此 API，並以您 API 的識別碼替代 `abcd1234`。

如需如何使用 AWS SDKs或 建立或更新 API 的更多範例 AWS CLI，請參閱[使用 AWS SDKs 的 API Gateway 動作](https://docs.aws.amazon.com/code-library/latest/ug/api-gateway_code_examples_actions.html)。

## 自動化 API 的設定作業
<a name="api-gateway-create-api-cli-sdk-iac"></a>

您可以使用 OpenAPI 或 Terraform 來建立 API，以自動建立和清除 AWS 資源 CloudFormation，而不是step-by-step建立 API。

### OpenAPI 3.0 定義
<a name="api-gateway-create-api-cli-sdk-template-OpenAPI"></a>

您可以將 OpenAPI 定義匯入 API Gateway。如需詳細資訊，請參閱[在 API Gateway 中使用 OpenAPI 開發 REST API](api-gateway-import-api.md)。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Simple PetStore (OpenAPI)",
    "description" : "Demo API created using OpenAPI",
    "version" : "2024-05-24T20:39:34Z"
  },
  "servers" : [ {
    "url" : "{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "Prod"
      }
    }
  } ],
  "paths" : {
    "/pets" : {
      "get" : {
        "responses" : {
          "200" : {
            "description" : "200 response",
            "content" : { }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "http",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "passthroughBehavior" : "when_no_match",
          "timeoutInMillis" : 29000
        }
      }
    },
    "/pets/{petId}" : {
      "get" : {
        "parameters" : [ {
          "name" : "petId",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "content" : { }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "http",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.path.id" : "method.request.path.petId"
          },
          "passthroughBehavior" : "when_no_match",
          "timeoutInMillis" : 29000
        }
      }
    }
  },
  "components" : { }
}
```

### AWS CloudFormation 範本
<a name="api-gateway-create-api-cli-sdk-template-CloudFormation"></a>

若要部署 CloudFormation 範本，請參閱[在 AWS CloudFormation 主控台上建立堆疊](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html)。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: Simple PetStore (AWS CloudFormation)
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetIdResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !Ref PetsResource
      PathPart: '{petId}'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      AuthorizationType: NONE
      Integration:
        Type: HTTP
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
        IntegrationResponses:
          - StatusCode: '200'
      MethodResponses:
        - StatusCode: '200'
  PetIdMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetIdResource
      HttpMethod: GET
      AuthorizationType: NONE
      RequestParameters: 
        method.request.path.petId: true
      Integration:
        Type: HTTP
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}
        RequestParameters:
          integration.request.path.id: method.request.path.petId
        IntegrationResponses:
          - StatusCode: '200'
      MethodResponses:
        - StatusCode: '200'
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: Prod
Outputs:
  ApiRootUrl:
    Description: Root Url of the API
    Value: !Sub 'https://${Api}.execute-api.${AWS::Region}.amazonaws.com/Prod'
```

### Terraform 組態
<a name="api-gateway-create-api-cli-sdk-template-terraform"></a>

如需 Terraform 的詳細資訊，請參閱 [Terraform](https://developer.hashicorp.com/terraform/intro)。

```
provider "aws" {
  region = "us-east-1" # Update with your desired region
}
resource "aws_api_gateway_rest_api" "Api" {
  name        = "Simple PetStore (Terraform)"
  description = "Demo API created using Terraform"
}
resource "aws_api_gateway_resource" "petsResource"{
    rest_api_id = aws_api_gateway_rest_api.Api.id
    parent_id = aws_api_gateway_rest_api.Api.root_resource_id
    path_part = "pets"
}
resource "aws_api_gateway_resource" "petIdResource"{
    rest_api_id = aws_api_gateway_rest_api.Api.id
    parent_id = aws_api_gateway_resource.petsResource.id
    path_part = "{petId}"
}
resource "aws_api_gateway_method" "petsMethodGet" {
  rest_api_id   = aws_api_gateway_rest_api.Api.id
  resource_id   = aws_api_gateway_resource.petsResource.id
  http_method   = "GET"
  authorization = "NONE"
}


resource "aws_api_gateway_method_response" "petsMethodResponseGet" {
    rest_api_id = aws_api_gateway_rest_api.Api.id 
    resource_id = aws_api_gateway_resource.petsResource.id
    http_method = aws_api_gateway_method.petsMethodGet.http_method 
    status_code ="200"
}

resource "aws_api_gateway_integration" "petsIntegration" {
  rest_api_id = aws_api_gateway_rest_api.Api.id
  resource_id = aws_api_gateway_resource.petsResource.id
  http_method = aws_api_gateway_method.petsMethodGet.http_method
  type        = "HTTP"
  
  uri                     = "http://petstore-demo-endpoint.execute-api.com/petstore/pets"
  integration_http_method = "GET"
  depends_on              = [aws_api_gateway_method.petsMethodGet]
}

resource "aws_api_gateway_integration_response" "petsIntegrationResponse" {
    rest_api_id = aws_api_gateway_rest_api.Api.id
    resource_id = aws_api_gateway_resource.petsResource.id
    http_method = aws_api_gateway_method.petsMethodGet.http_method
    status_code = aws_api_gateway_method_response.petsMethodResponseGet.status_code
}

resource "aws_api_gateway_method" "petIdMethodGet" {
    rest_api_id   = aws_api_gateway_rest_api.Api.id
    resource_id   = aws_api_gateway_resource.petIdResource.id
    http_method   = "GET"
    authorization = "NONE"
    request_parameters = {"method.request.path.petId" = true}
}

resource "aws_api_gateway_method_response" "petIdMethodResponseGet" {
    rest_api_id = aws_api_gateway_rest_api.Api.id 
    resource_id = aws_api_gateway_resource.petIdResource.id
    http_method = aws_api_gateway_method.petIdMethodGet.http_method 
    status_code ="200"
}


resource "aws_api_gateway_integration" "petIdIntegration" {
    rest_api_id = aws_api_gateway_rest_api.Api.id
    resource_id = aws_api_gateway_resource.petIdResource.id
    http_method = aws_api_gateway_method.petIdMethodGet.http_method
    type        = "HTTP"
    uri                     = "http://petstore-demo-endpoint.execute-api.com/petstore/pets/{id}"
    integration_http_method = "GET"
    request_parameters = {"integration.request.path.id" = "method.request.path.petId"}
    depends_on              = [aws_api_gateway_method.petIdMethodGet]
}

resource "aws_api_gateway_integration_response" "petIdIntegrationResponse" {
    rest_api_id = aws_api_gateway_rest_api.Api.id
    resource_id = aws_api_gateway_resource.petIdResource.id
    http_method = aws_api_gateway_method.petIdMethodGet.http_method
    status_code = aws_api_gateway_method_response.petIdMethodResponseGet.status_code
}


resource "aws_api_gateway_deployment" "Deployment" {
  rest_api_id = aws_api_gateway_rest_api.Api.id
  depends_on  = [aws_api_gateway_integration.petsIntegration,aws_api_gateway_integration.petIdIntegration ]
}
resource "aws_api_gateway_stage" "Stage" {
  stage_name    = "Prod"
  rest_api_id   = aws_api_gateway_rest_api.Api.id
  deployment_id = aws_api_gateway_deployment.Deployment.id
}
```

# 教學：建立私有 REST API
<a name="private-api-tutorial"></a>

在本教學課程中，您需建立私有 REST API。用戶端只能從您的 Amazon VPC 中存取 API。該 API 與公有網際網路隔離，這是一個常見安全要求。

本教學課程需要約 30 分鐘的時間完成。首先，您可以使用 CloudFormation 範本來建立 Amazon VPC、VPC 端點、 AWS Lambda 函數，並啟動您用來測試 API 的 Amazon EC2 執行個體。接著，您可以使用 AWS 管理主控台 建立私有 API 並連接資源政策，僅允許從您的 VPC 端點存取。最後，測試您的 API。

![\[您在本教學課程中建立私有 API 的概觀。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/private-api-tutorial-diagram.png)


若要完成本教學課程，您需要 AWS 帳戶和具有主控台存取權 AWS Identity and Access Management 的使用者。如需詳細資訊，請參閱[設定為使用 API Gateway](setting-up.md)。

在本教學課程中，您需使用 AWS 管理主控台。如需建立此 API 和所有相關資源的 CloudFormation 範本，請參閱 [template.yaml](samples/private-api-full-template.zip)。

**Topics**
+ [

## 步驟 1：建立相依性
](#private-api-tutorial-create-dependencies)
+ [

## 步驟 2：建立私有 API
](#private-api-tutorial-create-api)
+ [

## 步驟 3：建立方法與整合
](#private-api-tutorial-create-method)
+ [

## 步驟 4：連接資源政策
](#private-api-tutorial-attach-resource-policy)
+ [

## 步驟 5：部署 API
](#private-api-tutorial-deploy-api)
+ [

## 步驟 6：確認您的 API 無法公開存取
](#private-api-tutorial-test-private-api)
+ [

## 步驟 7：連接到 VPC 中的執行個體，並叫用您的 API
](#private-api-tutorial-connect-to-instance)
+ [

## 步驟 8：清理
](#private-api-tutorial-cleanup)
+ [

## 後續步驟：使用 自動化 CloudFormation
](#private-api-tutorial-next-steps)

## 步驟 1：建立相依性
<a name="private-api-tutorial-create-dependencies"></a>

下載並解壓縮[此 CloudFormation 範本](samples/private-api-starter-template.zip)。您可以使用範本為私有 API 建立所有相依性，包括 Amazon VPC、VPC 端點，以及做為 API 後端的 Lambda 函數。您可以稍後建立私有 API。

**建立 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 (堆疊名稱)**，輸入 **private-api-tutorial**，然後選擇 **Next (下一步)**。

1. 針對 **Configure stack options (設定堆疊選項)**，選擇 **Next (下一步)**。

1. 針對 **功能**，確認 CloudFormation 可以在您的帳戶中建立 IAM 資源。

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

CloudFormation 會為您的 API 佈建相依性，這可能需要幾分鐘的時間。當您 CloudFormation 堆疊的狀態為 **CREATE\$1COMPLETE** 時，請選擇**輸出**。請記下您的 VPC 端點 ID。您在本教程課程中的後續步驟需要它。

## 步驟 2：建立私有 API
<a name="private-api-tutorial-create-api"></a>

您可以建立私有 API，並僅允許 VPC 中的用戶端存取它。

**建立私有 API**

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

1. 選擇 **Create API (建立 API)**，然後針對 **REST API**，選擇 **Build (建置)**。

1. 針對 **API name (API 名稱)**，請輸入 **private-api-tutorial**。

1. 針對 **API 端點類型**，選取**私有**。

1. 針對 **VPC IDs**，輸入 CloudFormation 堆疊**輸出**中的 VPC 端點 ID。

1. 對於 **IP 位址類型**，請選擇 **Dualstack**。

1. 選擇**建立 API**。

## 步驟 3：建立方法與整合
<a name="private-api-tutorial-create-method"></a>

您可以建立 `GET` 方法和 Lambda 整合來處理對 API 的 `GET` 請求。當用戶端叫用您的 API 時，API Gateway 會將請求傳送至您在步驟 1 中建立的 Lambda 函數，然後傳回回應給用戶端。

**建立方法與整合**

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

1. 選擇您的 API。

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

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

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

1. 開啟 **Lambda 代理整合**。透過 Lambda 代理整合，API Gateway 會將事件傳送至具有定義結構的 Lambda，並將回應從您的 Lambda 函數轉換為 HTTP 回應。

1. 針對 **Lambda 函數**，選擇您在步驟 1 中使用 CloudFormation 範本建立的函數。函數的名稱以 **private-api-tutorial** 開頭。

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

## 步驟 4：連接資源政策
<a name="private-api-tutorial-attach-resource-policy"></a>

您可以將 [resource policy (資源政策)](apigateway-resource-policies.md) 連接至 API，該 API 允許用戶端僅透過 VPC 端點叫用您的 API。若要進一步限制存取 API，您也可以為 VPC 端點設定 [ VPC 端點政策](apigateway-vpc-endpoint-policies.md)，但這對於本教學課程而言並不需要。

**連接資源政策**

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

1. 選擇您的 API。

1. 選擇**資源政策**，然後選擇**建立政策**。

1. 輸入下列政策。將 *vpceID* 取代為 CloudFormation 堆疊**輸出**中的 VPC 端點 ID。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Deny",
               "Principal": "*",
               "Action": "execute-api:Invoke",
               "Resource": "execute-api:/*",
               "Condition": {
                   "StringNotEquals": {
                       "aws:sourceVpce": "vpce-abcd1234"
                   }
               }
           },
           {
               "Effect": "Allow",
               "Principal": "*",
               "Action": "execute-api:Invoke",
               "Resource": "execute-api:/*"
           }
       ]
   }
   ```

------

1. 選擇**儲存變更**。

## 步驟 5：部署 API
<a name="private-api-tutorial-deploy-api"></a>

接下來，您需部署 API，使其可供 Amazon VPC 中的用戶端使用。

**部署 API**

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

1. 選擇您的 API。

1. 選擇**部署 API**。

1. 針對**階段**，選取**新階段**。

1. 針對**階段名稱**，輸入 **test**。

1. 在**描述**，請輸入描述。

1. 選擇**部署**。

現在您已準備好測試 API。

## 步驟 6：確認您的 API 無法公開存取
<a name="private-api-tutorial-test-private-api"></a>

使用 `curl` 驗證您無法從 Amazon VPC 外部叫用 API。

**測試您的 API**

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

1. 選擇您的 API。

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

1. 在**階段詳細資訊**下，選擇複製圖示以複製 API 的調用 URL。URL 看起來像 `https://abcdef123.execute-api.us-west-2.amazonaws.com/test`。您在步驟 1 中建立的 VPC 端點已啟用私有 DNS，因此您可以使用提供的 URL 來叫用 API。

1. 使用 curl 嘗試從 VPC 外部叫用您的 API。

   ```
   curl https://abcdef123.execute-api.us-west-2.amazonaws.com/test
   ```

   curl 表示無法解析您的 API 端點。如果您收到不同的回應，請返回步驟 2，並確定您為 API 的端點類型選擇 **Private (私有)**。

   ```
   curl: (6) Could not resolve host: abcdef123.execute-api.us-west-2.amazonaws.com/test
   ```

接下來，連接到 VPC 中的 Amazon EC2 執行個體以叫用您的 API。

## 步驟 7：連接到 VPC 中的執行個體，並叫用您的 API
<a name="private-api-tutorial-connect-to-instance"></a>

接下來，從 Amazon VPC 中測試您的 API。若要存取您的私有 API，請連接到 VPC 中的 Amazon EC2 執行個體，然後使用 curl 來叫用您的 API。您可以使用 Systems Manager 工作階段管理員，在瀏覽器中連接到您的執行個體。

**測試您的 API**

1. 在 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 選擇 **Instances** (執行個體)。

1. 選擇您在步驟 1 中使用 CloudFormation 範本建立的名為 **private-api-tutorial** 的執行個體。

1. 選擇 **Connect (連線)**，然後選擇 **Session Manager (工作階段管理員)**。

1. 選擇 **Connect (連線)** 以對您的執行個體啟動瀏覽器型工作階段。

1. 在您的工作階段管理員工作階段中，使用 curl 來叫用您的 API。您可以叫用 API，因為您正在 Amazon VPC 中使用執行個體。

   ```
   curl https://abcdef123.execute-api.us-west-2.amazonaws.com/test
   ```

   驗證您收到回應 `Hello from Lambda!`。

![\[您可以使用工作階段管理員，從 Amazon VPC 中叫用您的 API。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/private-api-tutorial-invoke.png)


您成功建立了一個只能從 Amazon VPC 中存取的 API，然後驗證它可以運作。

## 步驟 8：清理
<a name="private-api-tutorial-cleanup"></a>

若要避免不必要的成本，請刪除您在此教學課程中建立的資源。下列步驟會刪除您的 REST API 和 CloudFormation 堆疊。

**刪除 REST API**

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

1. 在 **API** 頁面上，選取 API。選擇 **API 動作**、選擇**刪除 API**，然後確認您的選擇。

**刪除 CloudFormation 堆疊**

1. 在 https：//[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 開啟 CloudFormation 主控台。

1. 選取您的 CloudFormation 堆疊。

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

## 後續步驟：使用 自動化 CloudFormation
<a name="private-api-tutorial-next-steps"></a>

您可以自動化建立和清除本教學課程中涉及的所有 AWS 資源。如需完整的 CloudFormation 範本範例，請參閱 [template.yaml](samples/private-api-full-template.zip)。