

# 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 SDK 或 AWS CLI 创建 REST API](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)
+ [教程：利用跨账户 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 集成类型，可让您能够使用 Lambda 函数集成 API 方法（或整个 API）。Lambda 函数可以用 [Lambda 支持的任何语言](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)编写。由于这是代理集成，因此您可以随时更改 Lambda 函数实现，而无需重新部署您的 API。

在本教程中，您将执行以下操作：
+ 创建“Hello, World\$1” 要作为 API 的后端的 Lambda 函数。
+ 创建并测试“Hello, World\$1” API 与 Lambda 代理集成。

**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. 在导航窗格中，选择**函数**。

1. 选择**创建函数**。

1. 选择**从头开始创作**。

1. 在**基本信息**中，执行以下操作：

   1. 在**函数名称**中，输入 **GetStartedLambdaProxyIntegration**。

   1. 在**运行时**中，选择受支持的最新 **Node.js** 或 **Python** 运行时。

   1. 对于**架构**，请保留默认设置。

   1. 在**权限**下，展开**更改默认执行角色**。在**执行角色**下拉列表中，选择**从 AWS 策略模板创建新角色**。

   1. 在**角色名称**中，输入 **GetStartedLambdaBasicExecutionRole**。

   1. 将**策略模板**字段留空。

   1. 选择**创建函数**。

1. 在内联代码编辑器的**函数代码**下，复制/粘贴以下代码：

------
#### [ 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. 选择**部署**。

## 创建“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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 如果您是第一次使用 API Gateway，您会看到一个介绍服务特征的页面。在 **REST API** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 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，并在该 URL 的末尾添加 **/helloworld**。
**注意**  
如果您在 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，该 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` 函数记录调用，请用用于 Lambda 函数的适当策略来设置 IAM 角色，以创建 CloudWatch 流并向流中添加日志条目。Lambda 控制台将指导您创建所需的 IAM 角色和策略。

如果您设置 API 时不使用 API Gateway 控制台（例如，当[从 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)。

 与用于 Lambda 代理集成的 Lambda 函数 `GetStartedLambdaProxyIntegration` 相比，用于 Lambda 自定义集成的 `GetStartedLambdaIntegration` Lambda 函数仅从 API Gateway API 集成请求正文中获取输入。该函数可以返回任何 JSON 对象、字符串、数字、布尔值甚至是二进制 blob 形式的输出。相比而言，用于 Lambda 代理集成的 Lambda 函数可从任何请求数据获取输入，但必须返回特定 JSON 对象形式的输出。用于 Lambda 自定义集成的 `GetStartedLambdaIntegration` 函数可以使用 API 请求参数作为输入，前提是 API Gateway 在将客户端请求转发至后端之前，将所需的 API 请求参数映射至集成请求正文。要实现这一点，API 开发人员必须在创建 API 时创建一个映射模板并在 API 方法中对其进行配置。

现在，创建 `GetStartedLambdaIntegration` Lambda 函数。

**为 Lambda 自定义集成创建 `GetStartedLambdaIntegration` Lambda 函数**

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

1. 请执行下列操作之一：
   + 如果显示欢迎页面，请选择**立即开始使用**，然后选择**创建函数**。
   + 如果显示 **Lambda > 函数**列表页面，请选择**创建函数**。

1. 选择**从头开始创作**。

1. 在**从头开始创作**窗格中，执行以下操作：

   1. 在**名称**中，输入 **GetStartedLambdaIntegration** 作为 Lambda 函数名称。

   1. 在**运行时**中，选择受支持的最新 **Node.js** 或 **Python** 运行时。

   1. 对于**架构**，请保留默认设置。

   1. 在**权限**下，展开**更改默认执行角色**。在**执行角色**下拉列表中，选择**从 AWS 策略模板创建新角色**。

   1. 对于**角色名称**，输入您角色的名称（例如 **GetStartedLambdaIntegrationRole**）。

   1. 对于**策略模板**，选择**简单微服务权限**。

   1. 选择**创建函数**。

1. 在**配置函数**窗格中的**函数代码**下，执行以下操作：

   1. 复制本节开头部分列出的 Lambda 函数代码并将其粘贴到内联代码编辑器中。

   1. 对本部分中的所有其他字段保留默认选择。

   1. 选择**部署**。

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 控制台查看 IAM 角色 (`GetStartedLambdaIntegrationRole`)，此角色是在创建 Lambda 函数的过程中创建的。此 IAM 角色附加了两个内联策略。一个策略规定 Lambda 执行的最基本权限。它允许在创建 Lambda 函数的区域中为您账户的任何 CloudWatch 资源调用 CloudWatch `CreateLogGroup`。此策略还允许创建 CloudWatch 流和为 `GetStartedLambdaIntegration` Lambda 函数记录事件。

------
#### [ 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** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 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 函数的要求，通过添加正文映射模板来配置 `ANY` 方法的集成请求，以将传入的请求转换为 JSON 负载。

**配置集成请求**

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. 选择 **Save**。

## 测试 API 方法的调用
<a name="getting-started-new-get"></a>

 API Gateway 控制台提供了测试工具，以供您在部署 API 之前测试 API 的调用。您使用控制台的测试特征通过提交以下请求来测试 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. 在连接到 Internet 的本地计算机上打开终端窗口。

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 管理控制台，然后通过以下网址打开 AWS Lambda 控制台：[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)。

1. 从函数列表中选择 **GetStartedLambdaIntegration**，再选择**操作**，然后选择**删除函数**。当系统提示时，再次选择**删除**。

**删除相关联的 IAM 资源**

1. 通过以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 从**详细信息**中，选择**角色**。

1. 从角色列表中选择 **GetStartedLambdaIntegrationRole**，再选择**角色操作**，然后选择**删除角色**。按照控制台中的步骤删除该角色。

# 教程：利用跨账户 Lambda 代理集成创建 REST API
<a name="apigateway-cross-account-lambda-integrations"></a>

您现在可以使用其他 AWS Lambda 账户中的 AWS 函数作为 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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 如果您是第一次使用 API Gateway，您会看到一个介绍服务特征的页面。在 **REST API** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 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. 选择**创建函数**。

1. 选择**从头开始创作**。

1. 在**从头开始创作**下，执行以下操作：

   1. 对于**函数名称**，输入一个名称。

   1. 从**运行时**下拉列表中，选择受支持的 Node.js 运行时。

   1. 对于**架构**，请保留默认设置。

   1. 在**权限**下，展开**选择或创建执行角色**。您可以创建角色或选择现有角色。

   1. 选择**创建函数**以继续。

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 管理控制台，然后通过以下网址打开 AWS Lambda 控制台：[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/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 控制台，借助 PetStore 网站的 HTTP 集成来创建并测试简单的 REST API。API 定义预配置为 OpenAPI 2.0 文件。在将 API 定义加载到 API Gateway 中后，您可以使用 API Gateway 控制台来检查 API 的基本结构或直接部署并测试 API。

 PetStore 示例 API 支持客户端使用以下方法来访问 HTTP 后端网站 `http://petstore-demo-endpoint.execute-api.com/petstore/pets`。

**注意**  
本教程以 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. 通过以下网址登录到 Amazon 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_cn/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-new-console.png)

    在选择**创建 API** 之前，您可以向下滚动 OpenAPI 定义以了解此示例 API 的详细信息。

1. 在主导航窗格中，选择**资源**。新创建的 API 如下所示：

      
![\[导入到 API Gateway 控制台后的示例 API。\]](http://docs.aws.amazon.com/zh_cn/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_cn/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 随后将其路由至**方法响应**，然后再将其发送到客户端。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_cn/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_cn/apigateway/latest/developerguide/images/api-gateway-create-api-by-importing-example-post-method-test-result-new-console.png)

    该输出的**日志**条目显示了从方法请求到集成请求以及从集成响应到方法响应的状态更改。这可用于对导致请求失败的任何映射错误进行故障排除。此示例中没有应用任何映射：方法请求负载通过集成请求传递到后端；同样地，后端响应通过集成响应传递到方法响应。

    要使用客户端而非 API Gateway 的 test-invoke-request 特征来测试 API，您必须先将 API 部署至一个阶段。

1.  要部署示例 API，请选择**部署 API**。

      
![\[使用部署按钮部署 API，这样 API 调用方就可以调用 API。\]](http://docs.aws.amazon.com/zh_cn/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_cn/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 键提交请求。系统应返回一个包含以下 JSON 负载的 200 OK 响应：

   ```
   {
     "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 应用程序通过简单设置单个 API 方法即可访问集成的 HTTP 终端节点的多个资源或特征，例如整个网站。在 HTTP 代理集成中，API Gateway 会将客户端提交的方法请求传递至后端。传递的请求数据包括请求标头、查询字符串参数、URL 路径变量和负载。后端 HTTP 终端节点或 Web 服务器会对传入请求数据进行解析，以确定要返回的响应。在设置 API 方法后，HTTP 代理集成使得客户端和后端可以直接交互，而不受 API Gateway 的任何干预。不受支持的字符等已知问题除外，[Amazon API Gateway 重要说明](api-gateway-known-issues.md) 中列出了此类问题。

借助无所不包的代理资源 `{proxy+}` 和用于 HTTP 方法的“捕获全部”`ANY` 动词，您可以使用 HTTP 代理集成来创建单个 API 方法的 API。该方法会公开网站的一整套可公开访问的 HTTP 资源和操作。当后端 Web 服务器打开更多资源以供公开访问时，客户端可以通过相同的 API 设置来使用这些新资源。为了实现此功能，网站开发人员必须向客户端开发人员讲清楚什么是新资源以及适用于每个新资源的操作是什么。



作为快速介绍，以下教程演示了 HTTP 代理集成。在本教程中，我们将使用 API Gateway 控制台创建一个 API，以通过通用代理资源 `{proxy+}` 与 PetStore 网站集成，还将创建 `ANY` 的 HTTP 方法占位符。

**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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 如果您是第一次使用 API Gateway，您会看到一个介绍服务特征的页面。在 **REST API** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 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_cn/apigateway/latest/developerguide/images/api-gateway-simple-proxy-create-proxy-resource-new-console.png)

在此步骤中，您将使用代理集成将 `ANY` 方法与后端 HTTP 端点集成。在代理集成中，API Gateway 会将客户端提交的方法请求传递至后端，而不进行任何干预。

**创建 `ANY` 方法**

1. 选择 **/\$1proxy\$1\$1** 资源。

1. 选择 **ANY** 方法。

1. 在警告符号下，选择**编辑集成**。您无法部署具有方法但没有集成的 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_cn/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. 通过以下网址登录到 Amazon 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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 如果您是第一次使用 API Gateway，您会看到一个介绍服务特征的页面。在 **REST API** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 API**。在 **REST API** 下，选择**生成**。

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

1. （可选）对于**描述**，输入描述。

1. 将 **API 端点类型**设置保留为**区域**。

1. 为 **IP 地址类型**选择 **IPv4**。

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

**资源**树显示了不带任何方法的根资源 (`/`)。在本练习中，我们将创建一个与 PetStore 网站 (http://petstore-demo-endpoint.execute-api.com/petstore/pets) 进行 HTTP 自定义集成的 API。出于说明目的，我们将创建一个 `/pets` 资源作为根的子项，并在该资源上公开一个 GET 方法，以便客户端从 PetStore 网站上检索可用宠物项目列表。

**创建 /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 方法**，您必须选择一种受后端支持的方法。对于 `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_cn/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. 选择 **Test (测试)**。

   如果成功，**响应正文**将显示以下内容：

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

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

在此步骤中，您将部署 API，以便在 API Gateway 控制台外部对其进行调用。

**部署 API**

1. 选择**部署 API**。

1. 对于**阶段**，选择 **Prod**。

1. （可选）对于**描述**，输入描述。

1. 选择 **Deploy (部署)**。

#### 步骤 4：测试 API
<a name="getting-started-mappings-test"></a>

在此步骤中，您将转到 API Gateway 控制台外部，并使用您的 API 访问 HTTP 端点。

1. 在主导航窗格中，选择**阶段**。

1. 在**阶段详细信息**下，选择复制图标以复制您 API 的调用 URL。

   它应该如下所示：

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

1. 将此 URL 输入到新浏览器标签页的地址框中并在提交请求前将 `/pets/4` 附加到该 URL。

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 网关访问在您的 Amazon VPC 中运行的 Amazon ECS 服务。接下来，您创建一个 REST API，该 API 使用 VPC 链接 V2 连接到您的 Amazon ECS 服务。最后，测试您的 API。

当您调用 REST API 时，API Gateway 会通过 VPC 链接 V2 将请求路由到您的 Amazon ECS 服务，然后从该服务返回响应。

**注意**  
本教程以前支持 HTTP API，现在支持使用 VPC 链接 V2 的 REST API。

![\[您在本教程中创建的 REST API 的概述。\]](http://docs.aws.amazon.com/zh_cn/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 是一项容器管理服务，可让您轻松地在 cluster 上运行、停止和管理 Docker 容器。在本教程中，您将在 Amazon ECS 管理的无服务器基础设施上运行 cluster。

下载并解压此 [CloudFormation 模板](samples/rest-private-integration-tutorial.zip)，这将为服务创建所有依赖项，包括 Amazon VPC。您可以使用模板创建使用 Application Load Balancer 的 Amazon ECS 服务。

**创建 CloudFormation 堆栈**

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

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

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

1. 选择您下载的模板。

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

1. 对于**堆栈名称**，输入 **rest-api-private-integrations-tutorial**，然后选择**下一步**。

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

1. 对于**功能**，请确认 CloudFormation 可以在您的账户中创建 IAM 资源。

1. 选择**下一步**，然后选择**提交**。

CloudFormation 配置 ECS 服务，这可能需要几分钟的时间。当 CloudFormation 堆栈的状态为 **CREATE\$1COMPLETE** 时，您就可以继续下一步了。

## 步骤 2：创建 VPC 链接
<a name="http-api-private-integration-vpc-link"></a>

VPC 链接允许 API 网关访问 Amazon VPC 中的私有资源。您可以使用 VPC 链接允许客户端通过 REST API 访问您的 Amazon ECS 服务。

**要创建 VPC 链接**

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

1. 在主导航窗格上，选择 **VPC 链接**，然后选择**创建**。

   您可能需要选择菜单图标才能打开主导航窗格。

1. 对于**选择 VPC 链接版本**，选择 **VPC 链接 V2**。

1. 对于**名称**，请输入 **private-integrations-tutorial**。

1. 对于 **VPC**，选择已在步骤 1 中创建的 VPC。名称应以 **RestApiStack** 开头。

1. 对于**子网**，选择 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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择**创建 API**，然后为 **REST API** 选择**构建**。

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. 通过以下网址登录到 Amazon 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 服务，并使用了通过 VPC 链接 V2 访问 Amazon ECS 服务的 API Gateway REST API。

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

为避免不必要的成本，请删除作为本教程的一部分而创建的资源。以下步骤将删除您的 VPC 链接 V2、CloudFormation 堆栈和 REST API。

**要删除 REST API**

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

1. 在 **API** 页面上，选择一个 API。选择**操作**，选择**删除**，然后确认您的选择。

**要删除 VPC 链接**

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

1. 选择 **VPC 链接**。

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

**删除 CloudFormation 堆栈**

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

1. 选择您的 CloudFormation 堆栈。

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

# 教程：利用 AWS 集成创建 REST API
<a name="getting-started-aws-proxy"></a>

 [教程：利用 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 以公开集成的 Lambda 函数。此外，您还可以创建 API Gateway API 来公开其他AWS服务，例如 Amazon SNS、Amazon S3、Amazon Kinesis，甚至是 AWS Lambda。`AWS` 集成使其成为可能。Lambda 集成或 Lambda 代理集成是一种特殊情况，其中 Lambda 函数调用通过 API Gateway API 公开。

 所有 AWS 服务都支持通过专用 API 来公开其特征。但是，应用程序协议或编程接口可能因服务而异。具有 `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 获取 Amazon SNS 中与您的AWS账户相关联的主题列表。要了解如何在 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 管理控制台，然后使用以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/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. 通过以下网址登录到 Amazon 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**

1. 选择**部署 API**。

1. 对于**阶段**，选择**新建阶段**。

1. 对于**阶段名称**，输入 **test**。

1. （可选）对于**描述**，输入描述。

1. 选择 **Deploy (部署)**。

## 步骤 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服务代理和任何依赖它的 API 将无法正常运行。IAM 资源删除操作无法撤消。如果要再次使用 IAM 资源，您必须重新创建它。

**删除相关联的 IAM 资源**

1. 通过以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 在**详细信息**区域中，选择**角色**。

1. 选择 **APIGatewayAWSProxyExecRole**，然后依次选择**角色操作**、**删除角色**。在系统提示时，选择 **Yes, Delete**。

1. 在**详细信息**区域中，选择**策略**。

1. 选择 **APIGatewayAWSProxyExecPolicy**，然后选择**策略操作**和**删除**。系统提示时，选择**删除**。

 本演练到此结束。有关创建 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：创建使用 JSON 负载的 `POST` 方法以调用 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. 选择**创建角色**。

1. 在**选择受信任实体的类型**下，选择 **AWS 服务**。

1. 在**选择将使用此角色的服务**下，选择 **Lambda**。

1. 选择**下一步: 权限**。

1. 选择**创建策略**。

   新的**创建策略**控制台窗口将会打开。在该窗口中，执行以下操作：

   1. 在 **JSON** 选项卡中，将现有策略替换为以下策略：

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

****  

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

------

   1. 选择**查看策略**。

   1. 在**查看策略**下，执行以下操作：

      1. 在**名称**中，键入一个名称，如 **lambda\$1execute**。

      1. 选择**创建策略**。

1. 在原来的**创建角色**控制台窗口中，执行以下操作：

   1. 从下拉列表的**添加权限策略**下，选择您的 **lambda\$1execute** 策略。

      如果您未在策略列表中看到您的策略，请选择列表顶部的刷新按钮。（请勿刷新浏览器页面！）

   1. 选择**下一步: 标签**。

   1. 选择**下一步: 审核**。

   1. 对于**角色名称**，键入一个名称，如 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role**。

   1. 选择**创建角色**。

1. 从角色列表中，选择您的 **lambda\$1invoke\$1function\$1assume\$1apigw\$1role**。

1. 选择**信任关系**选项卡。

1. 选择**编辑信任关系**。

1. 使用以下策略替换现有策略：

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

****  

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

------

1. 选择**更新信任策略**。

1. 请记下您刚刚创建的角色的角色 ARN。您以后将需要它。

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

接下来，您将使用 Lambda 控制台创建 Lambda 函数。

1. 在 Lambda 控制台中，选择**创建函数**。

1. 选择**从头开始创作**。

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. 选择**部署**。

 此函数需要来自 `a` 输入参数的两个操作数 (`b` 和 `op`) 以及一个运算符 (`event`)。该输入是格式如下的 JSON 对象：

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

此函数会返回计算所得的结果 (`c`) 和输入。对于无效的输入，该函数将返回空值或“Invalid 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. 选择**保存**。

1. 选择**测试**。

1. 展开**执行结果: 成功**。您将看到以下内容：

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

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

以下过程介绍如何为您刚刚创建的 `Calc` Lambda 函数创建 API。在后续部分中，您将资源和方法添加到该 API。

**创建 API**

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

1. 如果您是第一次使用 API Gateway，您会看到一个介绍服务特征的页面。在 **REST API** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 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>

通过创建将查询字符串参数传递给 Lambda 函数的 `GET` 方法，启用要从浏览器中进行调用的 API。这种方法可能非常有用，特别是对于允许开放访问的 API。

创建 API 后，您将创建一个资源。通常情况下，根据应用程序逻辑将 API 资源组织成资源树形式。在此步骤中，您将创建一个 **/calc** 资源。

**创建 **/calc** 资源**

1. 选择**创建资源**。

1. 将**代理资源**保持为关闭状态。

1. 将**资源路径**保持为 `/`。

1. 对于**资源名称**，输入 **calc**。

1. 将 **CORS（跨源资源共享）**保持为关闭状态。

1. 选择**创建资源**。

通过创建将查询字符串参数传递给 Lambda 函数的 `GET` 方法，启用要从浏览器中进行调用的 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. 对于**操作类型**，选择**使用路径覆盖**。借助此选项，我们可以指定用来执行 `Calc` 函数的[调用](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html)操作的 ARN。

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_cn/apigateway/latest/developerguide/images/aws_proxy_lambda_calc_get_method_test_new_console.png)

## 集成 2：创建使用 JSON 负载的 `POST` 方法以调用 Lambda 函数
<a name="api-as-lambda-proxy-expose-post-method-with-json-body-to-call-lambda-function"></a>

通过创建使用 JSON 负载的 `POST` 方法以调用 Lambda 函数完成此操作，以便客户端必须将必要的输入提供给请求正文中的后端函数。为确保客户端上传正确的输入数据，您将对负载启用请求验证。

**创建使用 JSON 负载的 `POST` 方法**

1. 选择 **/calc** 资源，然后选择**创建方法**。

1. 对于**方法类型**，选择 **POST**。

1. 对于**集成类型**，选择 **AWS 服务**。

1. 对于 **AWS 区域**，选择您创建 Lambda 函数的 AWS 区域。

1. 对于 **AWS 服务**，选择 **Lambda**。

1. 将 **AWS 子域**保留为空白。

1. 对于 **HTTP 方法**，选择 **POST**。

1. 对于**操作类型**，选择**使用路径覆盖**。借助此选项，我们可以指定用来执行 `Calc` 函数的[调用](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html)操作的 ARN。

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_cn/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 编码，必须将除法运算符指定为 `%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. 对于 **operator**，输入 **\$1**。

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

1. 结果应该如下所示：  
![\[在 API Gateway 控制台中测试 GET 方法。\]](http://docs.aws.amazon.com/zh_cn/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. 对于 **operator**，输入 **\$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 和 Amazon S3 服务的区域。有关区域可用性，请参阅 [Amazon API Gateway 端点和配额](https://docs.aws.amazon.com/general/latest/gr/apigateway.html)。

**Topics**
+ [为 API 设置 IAM 权限以调用 Amazon S3 操作](#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 设置 IAM 权限以调用 Amazon S3 操作
<a name="api-as-s3-proxy-iam-permissions"></a>

 要允许 API 调用 Amazon S3 操作，您必须已将适当的 IAM 策略附加到 IAM 角色。在此步骤中，您将创建新 IAM 角色。

**创建 AWS 服务代理执行角色**

1. 登录 AWS 管理控制台，然后使用以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/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.  在创建 Amazon S3 桶的同一 AWS 区域，创建名为 **MyS3** 的 API。此 API 的根资源 (**/**) 表示 Amazon S3 服务。在此步骤中，您将创建另外两个资源：**/\$1folder\$1** 和 **/\$1item\$1**。

1. 选择**创建资源**。

1. 将**代理资源**保持为关闭状态。

1. 对于**资源路径**，选择 `/`。

1. 对于**资源名称**，输入 **\$1folder\$1**。

1. 将 **CORS（跨源资源共享）**保持为未选中。

1. 选择**创建资源**。

1. 选择 **/\$1folder\$1** 资源，然后选择**创建资源**。

1. 使用上述步骤创建 **/\$1folder\$1** 的子资源，名为 **\$1item\$1**。

   最终的 API 应类似以下内容：

      
![\[在 API Gateway 中创建 API 作为 Amazon S3 代理\]](http://docs.aws.amazon.com/zh_cn/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 REST API 路径样式请求](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAPI.html)转发到 Amazon S3，其中 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_cn/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. 对于 **Timestamp** 标头，输入 **integration.response.header.Date** 作为映射值。

1. 选择**保存**。结果应类似以下内容：

      
![\[将集成响应标头映射到方法响应标头\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/aws_proxy_s3_setup_integration_response_headers_new_console.png)

1. 在**集成响应**选项卡的**集成响应**下，选择**创建响应**。

1. 对于 **HTTP 状态正则表达式**，输入 **4\$1d\$12\$1**。这会将所有 4xx HTTP 响应状态代码映射到方法响应。

1. 对于**方法响应状态代码**，选择 **400**。

1. 选择**创建**。

1. 重复以下步骤，为 500 方法响应创建集成响应。对于 **HTTP 状态正则表达式**，输入 **5\$1d\$12\$1**。

作为一个良好做法，您可以测试到目前为止已配置的 API。

**测试 `GET /` 方法**

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

1. 选择**测试**。结果应类似下图内容：

      
![\[测试 API 根 GET 存储桶结果\]](http://docs.aws.amazon.com/zh_cn/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_cn/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}` 资源的更多应用，请转至[作为 Amazon S3 代理的示例 API 的 OpenAPI 定义](api-as-s3-proxy-export-swagger-with-extensions.md)参阅示例 API。

**对项目资源公开 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_cn/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. 在集成请求（用于上传）和集成响应（用于下载）中，将**内容处理** 设置为 `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 相比，此 API 包含更多 Amazon S3 操作。此 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)。

要了解如何使用支持 AWS IAM 授权的 [Postman](https://www.postman.com/) 调用此 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>

为了提供端到端教程，我们现在演示如何使用支持AWS IAM 授权的 [Postman](https://www.postman.com/) 调用 API。<a name="api-as-s3-proxy-test-using-postman-steps"></a>

**使用 Postman 调用我们的 Amazon S3 代理 API**

1. 部署或重新部署 API。记下位于**阶段编辑器**顶部的**调用 URL** 旁边显示的 API 的基本 URL。

1. 启动 Postman。

1. 选择**授权**，然后选择 `AWS Signature`。分别在 **AccessKey** 和 **SecretKey** 输入字段中键入 IAM 用户的访问密钥 ID 和秘密访问密钥。在 **AWS 区域**文本框中输入将您的 API 部署到的 AWS 区域。在**服务名称**输入字段中输入 `execute-api`。

   您可以在 IAM 管理控制台的 IAM 用户账户的**安全凭证**选项卡中创建一对密钥。

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 和 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` 操作。

 您可以将此处提供的说明应用于其他 Kinesis 操作。有关 Kinesis 操作的完整列表，请参阅 [Amazon Kinesis API 参考](https://docs.aws.amazon.com/kinesis/latest/APIReference/Welcome.html)。

 您可以使用 API Gateway [导入 API](https://docs.aws.amazon.com/apigateway/latest/api/API_ImportRestApi.html) 将示例 API 导入到 API Gateway 中，而不是使用 API Gateway 控制台创建示例 API。有关如何使用 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 管理控制台，然后使用以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 如果您是第一次使用 API Gateway，您会看到一个介绍服务特征的页面。在 **REST API** 下，选择**生成**。当**创建示例 API** 弹出框出现时，选择**确定**。

   如果这不是您首次使用 API Gateway，请选择**创建 API**。在 **REST API** 下，选择**生成**。

1. 选择**新 API**。

1. 在 **API 名称**中，输入 **KinesisProxy**。对于所有其他字段，保留默认值。

1. （可选）对于**描述**，输入描述。

1. 为 **IP 地址类型**选择 **IPv4**。

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

 API 创建完成后，API Gateway 控制台将显示**资源**页面，该页面仅包含 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 方法**，选择 **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')"
   }
   ```

    此映射模板将使用客户端提供的 URL 路径名称 `DELETE /streams/{stream-name}` 为 `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` 值 (该值通过调用 `GetShardIterator` 辅助标记操作获得) 作为输入，我们在 `GET` 资源 (`ShardIterator`) 上使用了 `/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_cn/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` 方法为辅助标记方法，用于在调用 `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 控制台中的**测试**选项，输入现有流名称作为 `stream-name` **路径**变量值，将 `shard-id` **查询字符串**设置为现有 `ShardId` 值（例如 `shard-000000000004`），然后选择**测试**。

    成功的响应负载与以下输出类似：

   ```
   {
     "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.  在**集成请求**部分中，添加以下正文映射模板，以便为 Kinesis 中的 `GetRecords` 操作将 `Shard-Iterator` 标头参数值映射到 JSON 负载的 `ShardIterator` 属性值。

   ```
   {
       "ShardIterator": "$input.params('Shard-Iterator')"
   }
   ```

1.  使用 API Gateway 控制台中的**测试**选项，输入现有流名称作为 `stream-name` **路径**变量值，将 `Shard-Iterator` **标头**设置为从 `GET /streams/{stream-name}/sharditerator` 方法的测试运行中获得的 `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 SDK 或 AWS CLI 创建 REST API
<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 的更多信息，请参阅 [What's the AWS SDK for JavaScript?](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html) 有关适用于 Python 的 SDK（Boto3）的更多信息，请参阅 [适用于 Python (Boto3) 的 AWS SDK](https://docs.aws.amazon.com/pythonsdk)。有关 AWS CLI 的更多信息，请参阅 [What is the 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 SDK 设置边缘优化的 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 的 API ID 为 `abcd1234`，根资源 ID 为 `efg567`。您可以在 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` 资源的资源 ID 为 `aaa111`。您可以在 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}` 资源的资源 ID 为 `bbb222`。您可以在 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. 使用以下示例对 HTTP 端点配置 `GET /pets` 方法的集成。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. 使用以下示例对 HTTP 端点配置 `GET /pets/{petId}` 方法的集成。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. 使用以下示例测试 `GET /pets/{petId}` 方法，其中 `petId` 为 3：

------
#### [ 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 并将 `abcd1234` 替换为 API 的标识符，测试此 API。

有关如何使用 AWS SDK 或 AWS CLI 创建或更新 API 的更多示例，请参阅 [Actions for API Gateway using AWS SDKs](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>

在创建 API 时，您不必按部就班地创建，而是可以通过使用 OpenAPI、CloudFormation 或 Terraform 来自动创建和清理 AWS 资源。

### 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_cn/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：创建私有密钥](#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. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

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

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

1. 选择您下载的模板。

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

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

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

1. 对于**功能**，请确认 CloudFormation 可以在您的账户中创建 IAM 资源。

1. 选择**下一步**，然后选择**提交**。

CloudFormation 为 API 配置依赖项，这可能需要几分钟的时间。当 CloudFormation 堆栈的状态为 **CREATE\$1COMPLETE** 时，请选择**输出**。记下您的 VPC 端点 ID。在本教程的后续步骤中，您需要使用该信息。

## 步骤 2：创建私有密钥
<a name="private-api-tutorial-create-api"></a>

您可以创建一个私有 API，以便只允许 VPC 中的客户端可以访问。

**要创建私有 API**

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

1. 选择**创建 API**，然后为 **REST API** 选择**构建**。

1. 对于 **API Name (API 名称)**，请输入 **private-api-tutorial**。

1. 对于 **API 端点类型**，选择**私有**。

1. 对于 **VPC 端点 ID**，请输入 CloudFormation 堆栈的**输出**中的 VPC 端点 ID。

1. 对于 **IP 地址类型**，选择**双堆栈**。

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

## 步骤 3：创建方法和集成
<a name="private-api-tutorial-create-method"></a>

您可以创建 `GET` 方法和 Lambda 集成来处理对 API 的 `GET` 请求。当客户端调用 API 时，API Gateway 会将请求发送到您在步骤 1 中创建的 Lambda 函数，然后向客户端返回响应。

**要创建方法和集成**

1. 通过以下网址登录到 Amazon 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>

您将[资源策略](apigateway-resource-policies.md)附加到 API，该策略允许客户端仅通过 VPC 端点调用您的 API。要进一步限制对 API 的访问，您还可以为 VPC 端点配置 [VPC 端点策略](apigateway-vpc-endpoint-policies.md)，但这对于本教程并不是必需的。

**要附加资源策略**

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

1. 选择 API。

1. 选择**资源策略**，然后选择**创建策略**。

1. 输入以下策略。使用来自您 ‭CloudFormation 堆栈的 ‭**输出**‭ 中的 VPC 端点 ID 替换 *vpceID*‬。

------
#### [ 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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择 API。

1. 选择**部署 API**。

1. 对于**阶段**，选择**新建阶段**。

1. 对于**阶段名称**，输入 **test**。

1. （可选）对于**描述**，输入描述。

1. 选择 **Deploy (部署)**。

现在您已经准备好测试 API 了。

## 步骤 6：验证您的 API 是否不可公开访问
<a name="private-api-tutorial-test-private-api"></a>

用 `curl` 于验证您是否无法从 Amazon VPC 之外调用 API。

**要测试您的 API**

1. 通过以下网址登录到 Amazon 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 的端点类型选择**私有**。

   ```
   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. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 选择**实例**。

1. 选择您在步骤 1 中使用 CloudFormation 模板创建的名为 **private-api-tutorial** 的实例。

1. 选择**连接**，然后选择**会话管理器**。

1. 选择**连接**可启动与实例的基于浏览器的会话。

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_cn/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. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 在 **API** 页面上，选择一个 API。选择 **API 操作**，选择**删除 API**，然后确认您的选择。

**删除 CloudFormation 堆栈**

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

1. 选择您的 CloudFormation 堆栈。

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

## 接下来的步骤：通过 实现自动化CloudFormation
<a name="private-api-tutorial-next-steps"></a>

您可以自动创建和清理本教程中涉及的所有AWS资源。如需完整的示例 CloudFormation 模板，请参阅 [template.yaml](samples/private-api-full-template.zip)。