

# 教程：创建 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.amazonaws.cn/AmazonS3/latest/API/API_ListBuckets.html)。
+ 在 Folder 资源上公开 GET 以[查看 Amazon S3 存储桶中所有对象的列表](https://docs.amazonaws.cn/AmazonS3/latest/API/API_ListObjects.html)。
+ 在 Folder/Item 资源上公开 GET 以[从 Amazon S3 存储桶查看或下载对象](https://docs.amazonaws.cn/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.amazonaws.cn/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 角色。

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

1. 登录 Amazon Web Services 管理控制台，然后使用以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.amazonaws.cn/iam/)。

1. 选择**角色**。

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

1.  在**选择受信任实体的类型**下选择 **Amazon 服务**，然后选择 **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 桶的同一 Amazon Web Services 区域，创建名为 **MyS3** 的 API。此 API 的根资源 (**/**) 表示 Amazon S3 服务。在此步骤中，您将创建另外两个资源：**/{folder}** 和 **/{item}**。

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

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

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

1. 对于**资源名称**，输入 **{folder}**。

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

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

1. 选择 **/{folder}** 资源，然后选择**创建资源**。

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

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

    

## 公开 API 方法以列出调用方的 Amazon S3 存储桶
<a name="api-root-get-as-s3-get-service"></a>

在获取调用方的 Amazon S3 存储桶列表的过程中，涉及针对 Amazon S3 调用 [GET 服务](https://docs.amazonaws.cn/AmazonS3/latest/API/API_ListBuckets.html)操作。在 API 的根资源 (**/**) 上，创建 GET 方法。按如下所示，配置 GET 方法以与 Amazon S3 集成。

**创建和初始化 API 的 `GET /` 方法**

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

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

1. 对于**集成类型**，选择 **Amazon Web Services 服务**。

1. 对于 **Amazon Web Services 区域**，选择您创建 Amazon S3 桶的 Amazon Web Services 区域。

1. 对于 **Amazon Web Services 服务**，选择 **Amazon Simple Storage Service**。

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

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

1. 对于**操作类型**，选择**使用路径覆盖**。

   利用路径覆盖，API Gateway 可将客户端请求作为对应的 [Amazon S3 REST API 路径样式请求](https://docs.amazonaws.cn/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`。

    

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. 选择**保存**。结果应类似以下内容：

    

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

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

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

1. 选择**创建**。

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

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

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

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

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

    

## 公开 API 方法以访问 Amazon S3 存储桶
<a name="api-folder-operations-as-s3-bucket-actions"></a>

为了使用 Amazon S3 存储桶，您在 /{folder} 资源上公开 `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. 选择 **/{folder}** 资源，然后选择**创建方法**。

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

1. 对于**集成类型**，选择 **Amazon Web Services 服务**。

1. 对于 **Amazon Web Services 区域**，选择您创建 Amazon S3 桶的 Amazon Web Services 区域。

1. 对于 **Amazon Web Services 服务**，选择 **Amazon Simple Storage Service**。

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

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

1. 对于**操作类型**，选择**使用路径覆盖**。

1. 对于**路径覆盖**，输入 **{bucket}**。

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

   测试结果将包含桶中对象的列表。

    

## 公开 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. 选择 **/{item}** 资源，然后选择**创建方法**。

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

1. 对于**集成类型**，选择 **Amazon Web Services 服务**。

1. 对于 **Amazon Web Services 区域**，选择您创建 Amazon S3 桶的 Amazon Web Services 区域。

1. 对于 **Amazon Web Services 服务**，选择 **Amazon Simple Storage Service**。

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

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

1. 对于**操作类型**，选择**使用路径覆盖**。

1. 对于**路径覆盖**，输入 **{bucket}/{object}**。

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

   响应正文将包含该项目的内容。

    

   该请求正确返回纯文本（“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)。