

# 开发 API Gateway 中的 REST API
<a name="rest-api-develop"></a>

 在 Amazon API Gateway 中，您可以将 REST API 构建为称为 API Gateway [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)的可编程实体的集合。例如，您可以使用 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源表示可以包含[资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)实体集合的 API。

每个 `Resource` 实体可以具有一个或多个 [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) 资源。`Method` 是客户端提交的传入请求，可以包含以下请求参数：路径参数、标头或查询字符串参数。此外，根据 HTTP 方法，请求可以包含正文。您的方法定义了客户端如何访问公开的 `Resource`。要将 `Method` 与后端端点（也称为集成端点）进行集成，可创建 [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 资源。这会将传入的请求转发到指定的集成端点 URI。如有必要，您可以转换请求参数或请求正文以满足后端要求，也可以创建代理集成，其中，API Gateway 将整个请求以标准化格式发送到集成端点 URI，然后直接将响应发送到客户端。

对于响应，您可以创建 [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) 资源来表示客户端收到的响应，然后创建 [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源来表示后端返回的响应。使用集成响应来转换后端响应数据，然后将数据返回给客户端，或者按原样将后端响应传递给客户端。

## REST API 的示例资源
<a name="rest-api-develop-example"></a>

下图显示了 API Gateway 如何为 HTTP 代理和 `GET /pets` 资源的 HTTP 非代理集成实现此请求/响应模型。客户端将 `x-version:beta` 标头发送到 API Gateway，而 API Gateway 将 `204` 状态代码发送给客户端。

在非代理集成中，API Gateway 通过修改集成请求和集成响应来执行数据转换，以满足后端要求。在非代理集成中，您可以在方法请求中访问正文，但可以在集成请求中对其进行转换。当集成端点返回带有正文的响应时，您可以在集成响应中对其进行访问和转换。您不能修改方法响应中的正文。

在代理集成中，集成端点修改请求和响应。API Gateway 不会修改集成请求或集成响应，而是按原样将传入请求发送到后端。

无论集成类型如何，客户端都已向 API Gateway 发送请求，API Gateway 都已同步响应。

------
#### [ Non-proxy integration ]

![\[API Gateway 非代理集成图\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/develop-non-proxy.png)


------
#### [ Proxy integration ]

![\[API Gateway 代理集成图\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/develop-proxy.png)


------

以下示例执行日志显示了 API Gateway 在上一个示例中记录的内容。为清楚起见，已移除了一些值和初始日志：

------
#### [ Non-proxy integration ]

```
Wed Feb 12 23:56:44 UTC 2025 : Starting execution for request: abcd-1234-5678
Wed Feb 12 23:56:44 UTC 2025 : HTTP Method: GET, Resource Path: /pets
Wed Feb 12 23:56:44 UTC 2025 : Method request path: {}
Wed Feb 12 23:56:44 UTC 2025 : Method request query string: {}
Wed Feb 12 23:56:44 UTC 2025 : Method request headers: {x-version=beta}
Wed Feb 12 23:56:44 UTC 2025 : Method request body before transformations: 
Wed Feb 12 23:56:44 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:56:44 UTC 2025 : Endpoint request headers: {app-version=beta}
Wed Feb 12 23:56:44 UTC 2025 : Endpoint request body after transformations: 
Wed Feb 12 23:56:44 UTC 2025 : Sending request to http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:56:45 UTC 2025 : Received response. Status: 200, Integration latency: 123 ms
Wed Feb 12 23:56:45 UTC 2025 : Endpoint response headers: {Date=Wed, 12 Feb 2025 23:56:45 GMT}
Wed Feb 12 23:56:45 UTC 2025 : Endpoint response body before transformations:
Wed Feb 12 23:56:45 UTC 2025 : Method response body after transformations: (null)
Wed Feb 12 23:56:45 UTC 2025 : Method response headers: {X-Amzn-Trace-Id=Root=1-abcd-12345}
Wed Feb 12 23:56:45 UTC 2025 : Successfully completed execution
Wed Feb 12 23:56:45 UTC 2025 : Method completed with status: 204
```

------
#### [ Proxy integration ]

```
Wed Feb 12 23:59:42 UTC 2025 : Starting execution for request: abcd-1234-5678
Wed Feb 12 23:59:42 UTC 2025 : HTTP Method: GET, Resource Path: /pets
Wed Feb 12 23:59:42 UTC 2025 : Method request path: {}
Wed Feb 12 23:59:42 UTC 2025 : Method request query string: {}
Wed Feb 12 23:59:42 UTC 2025 : Method request headers: {x-version=beta}
Wed Feb 12 23:59:42 UTC 2025 : Method request body before transformations: 
Wed Feb 12 23:59:42 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:59:42 UTC 2025 : Endpoint request headers: { x-version=beta}
Wed Feb 12 23:59:42 UTC 2025 : Endpoint request body after transformations: 
Wed Feb 12 23:59:42 UTC 2025 : Sending request to http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:59:43 UTC 2025 : Received response. Status: 204, Integration latency: 123 ms
Wed Feb 12 23:59:43 UTC 2025 : Endpoint response headers: {Date=Wed, 12 Feb 2025 23:59:43 GMT}
Wed Feb 12 23:59:43 UTC 2025 : Endpoint response body before transformations: 
Wed Feb 12 23:59:43 UTC 2025 : Method response body after transformations:
Wed Feb 12 23:59:43 UTC 2025 : Method response headers: {Date=Wed, 12 Feb 2025 23:59:43 GMT}
Wed Feb 12 23:59:43 UTC 2025 : Successfully completed execution
Wed Feb 12 23:59:43 UTC 2025 : Method completed with status: 204
```

------

要导入类似的 API 并在 AWS 管理控制台中对其进行测试，请参阅[示例 API](api-gateway-create-api-from-example.md)。

## 用于开发的其它 REST API 功能
<a name="rest-api-develop-details"></a>

API Gateway 支持用于开发 REST API 的其它功能。例如，为有助于您的客户了解您的 API，您可以提供 API 的文档。要实现这一点，请为受支持的 API 实体添加一个 [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) 资源。

要控制客户端调用 API 的方式，请使用 [IAM 权限](permissions.md)、[Lambda 授权方](apigateway-use-lambda-authorizer.md)或 [Amazon Cognito 用户池](apigateway-integrate-with-cognito.md)。要计量 API 的使用情况，请设置[使用计划](api-gateway-api-usage-plans.md)以限制 API 请求。您可在创建或更新 API 时启用这些选项。

下图显示了可用于 REST API 开发的功能，以及在请求/响应模型中配置这些功能的位置。

![\[API Gateway 功能图\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/develop-features.png)


有关如何创建 API 的介绍，请参阅[教程：利用 Lambda 代理集成创建 REST API](api-gateway-create-api-as-simple-proxy-for-lambda.md)。要了解有关开发 REST API 时可能使用的 API Gateway 功能的更多信息，请参阅以下主题。这些主题包含概念信息以及您可以使用 API Gateway 控制台、API Gateway REST API、AWS CLI 或其中一个 AWS SDK 执行的过程。

**Topics**
+ [REST API 的示例资源](#rest-api-develop-example)
+ [用于开发的其它 REST API 功能](#rest-api-develop-details)
+ [API Gateway 中针对 REST API 的 API 端点类型](api-gateway-api-endpoint-types.md)
+ [API Gateway 中的 REST API 安全策略](apigateway-security-policies.md)
+ [API Gateway 中 REST API 的 IP 地址类型](api-gateway-ip-address-type.md)
+ [API Gateway 中用于 REST API 的方法](how-to-method-settings.md)
+ [在 API Gateway 中控制和管理对 REST API 的访问](apigateway-control-access-to-api.md)
+ [针对 API Gateway 中的 REST API 的集成](how-to-integration-settings.md)
+ [针对 API Gateway 中的 REST API 的请求验证](api-gateway-method-request-validation.md)
+ [针对 API Gateway 中 REST API 的数据转换](rest-api-data-transformations.md)
+ [针对 API Gateway 中 REST API 的网关响应](api-gateway-gatewayResponse-definition.md)
+ [针对 API Gateway 中的 REST API 的 CORS](how-to-cors.md)
+ [针对 API Gateway 中的 REST API 的二进制媒体类型](api-gateway-payload-encodings.md)
+ [调用 API Gateway 中的 REST API](how-to-call-api.md)
+ [在 API Gateway 中使用 OpenAPI 开发 REST API](api-gateway-import-api.md)

# API Gateway 中针对 REST API 的 API 端点类型
<a name="api-gateway-api-endpoint-types"></a>

*[API 端点](api-gateway-basic-concept.md#apigateway-definition-api-endpoints)* 类型指的是 API 的主机名。API 端点类型可以是*边缘优化的*、*区域性的*或*私有的*，具体取决于大部分 API 流量源自何处。

## 边缘优化的 API 端点
<a name="api-gateway-api-endpoint-types-edge-optimized"></a>

*[边缘优化的 API 端点](api-gateway-basic-concept.md#apigateway-definition-edge-optimized-api-endpoint)*通常将请求路由至最近的 CloudFront 入网点（PoP），这在您的客户呈地理分布的情况下可能会有所帮助。这是 API Gateway REST API 的默认端点类型。

边缘优化 API 利用 [HTTP 标头](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)的名称（例如，`Cookie`）。

CloudFront 在转发请求到源之前以自然顺序按 Cookie 名称对 HTTP Cookie 进行排序。有关 CloudFront 如何处理 Cookie 的更多信息，请参阅[基于 Cookie 缓存内容](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Cookies.html)。

您用于边缘优化 API 的任何自定义域名都适用于所有区域。

## 区域 API 端点
<a name="api-gateway-api-endpoint-types-regional"></a>

*[区域 API 端点](api-gateway-basic-concept.md#apigateway-definition-regional-api-endpoint)*适用于同一区域中的客户端。当在 EC2 实例上运行的客户端调用同一区域中的 API，或 API 用于为具有高需求的少数客户端提供服务时，区域 API 可以降低连接开销。

对于区域 API，您使用的任何自定义域名都特定于部署了该 API 的区域。如果在多个区域中部署区域 API，则它可以在所有区域中具有相同的自定义域名。您可以将自定义域与 Amazon Route 53 一起使用来执行诸如[基于延迟的路由](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-latency)之类的任务。有关更多信息，请参阅 [在 API Gateway 中设置区域自定义域名](apigateway-regional-api-custom-domain-create.md) 和 [为 API Gateway API 设置边缘优化的自定义域名](how-to-edge-optimized-custom-domain-name.md)。

区域 API 端点按原样传递所有标头名称。

**注意**  
在 API 客户端在地理上分散的案例中，使用区域 API 端点以及您自己的 Amazon CloudFront 分配可能仍然有意义，这可确保 API Gateway 不会将 API 与服务控制的 CloudFront 分配关联。有关此使用案例的更多信息，请参阅[如何使用我自己的 CloudFront 分配设置 API Gateway？](https://repost.aws/knowledge-center/api-gateway-cloudfront-distribution)

## 私有 API 端点
<a name="api-gateway-api-endpoint-types-private"></a>

*[私有 API 端点](api-gateway-basic-concept.md#apigateway-definition-private-api-endpoint)* 是一个只能使用接口 VPC 端点从 Amazon Virtual Private Cloud (VPC) 访问的 API 端点，该接口是您在 VPC 中创建的端点网络接口 (ENI)。有关更多信息，请参阅 [API Gateway 中的私有 REST API](apigateway-private-apis.md)。

私有 API 端点按原样传递所有标头名称。

# 在 API Gateway 中更改公有或私有 API 端点类型
<a name="apigateway-api-migration"></a>

更改 API 端点类型要求您更新 API 的配置。您可以使用 API Gateway 控制台、AWS CLI 或适用于 API Gateway 的AWS开发工具包更改现有 API 类型。端点类型无法再次进行更改，直到当前更改完成，但您的 API 将可用。

支持以下端点类型更改：
+ 从边缘优化到区域或私有
+ 从区域到边缘优化或私有
+ 从私有到区域

您不能将私有 API 更改为边缘优化的 API。

如果您正在将公有 API 从边缘优化更改为区域（或反之），请注意边缘优化 API 可能与区域 API 具有不同的行为。例如，边缘优化的 API 删除 `Content-MD5` 标头。传递到后端的任意 MD5 哈希值可以表示在请求字符串参数或正文属性中。但是，区域 API 会传递此标头映射，虽然它可能会将标头名称重新映射到某个其它名称。了解区别有助于您决定如何将边缘优化的 API 更新为区域 API，或者从区域 API 更新为边缘优化的 API。

**Topics**
+ [使用 API Gateway 控制台更改 API 端点类型](#migrate-api-using-console)
+ [使用 AWS CLI 更改 API 端点类型](#migrate-api-using-aws-cli)

## 使用 API Gateway 控制台更改 API 端点类型
<a name="migrate-api-using-console"></a>

要更改 API 的 API 端点类型，请执行以下步骤：

**将一个公有端点从区域转换为边缘优化（以及反之）**

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

1. 选择一个 REST API。

1. 选择 **API 设置**。

1. 在 **API 详细信息**部分中，选择**编辑**。

1. 对于 **API 端点类型**，选择**边缘优化**或**区域**。

1. 选择**保存更改**。

1. 重新部署您的 API，以使更改生效。

**将私有端点转换为区域端点**

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

1. 选择一个 REST API。

1. 编辑 API 的资源策略以删除对 VPC 或 VPC 端点的任何提及，以便 API 从您的 VPC 之外以及在您的 VPC 之内进行的调用成功。

1. 选择 **API 设置**。

1. 在 **API 详细信息**部分中，选择**编辑**。

1. 对于 **API 端点类型**，选择**区域**。

1. 选择**保存更改**。

1. 从 API 中删除资源策略。

1. 重新部署您的 API，以使更改生效。

   由于您要将端点类型从私有迁移到区域，因此 API Gateway 会将 IP 地址类型更改为 IPv4。有关更多信息，请参阅 [API Gateway 中 REST API 的 IP 地址类型](api-gateway-ip-address-type.md)。

**将区域端点转换为私有端点**

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

1. 选择一个 REST API。

1. 创建资源策略来授予对您的 VPC 或 VPC 端点的访问权限。有关更多信息，请参阅 [步骤 3：为私有 API 设置资源策略](apigateway-private-api-create.md#apigateway-private-api-set-up-resource-policy)。

1. 选择 **API 设置**。

1. 在 **API 详细信息**部分中，选择**编辑**。

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

1. （可选）对于 **VPC 端点 ID**，选择您要与私有 API 关联的 VPC 端点 ID。

1. 选择**保存更改**。

1. 重新部署您的 API，以使更改生效。

   由于您要将端点类型从区域迁移到私有，因此 API Gateway 会将 IP 地址类型更改为双堆栈。有关更多信息，请参阅 [API Gateway 中 REST API 的 IP 地址类型](api-gateway-ip-address-type.md)。

## 使用 AWS CLI 更改 API 端点类型
<a name="migrate-api-using-aws-cli"></a>

使用以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令将边缘优化的 API 更新为区域 API：

```
aws apigateway update-rest-api \
    --rest-api-id a1b2c3 \
    --patch-operations op=replace,path=/endpointConfiguration/types/EDGE,value=REGIONAL
```

成功的响应包含 `200 OK` 状态代码以及与以下类似的负载：

```
{
    "createdDate": "2017-10-16T04:09:31Z",
    "description": "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints",
    "endpointConfiguration": {
        "types": "REGIONAL"
    },
    "id": "a1b2c3",
    "name": "PetStore imported as edge-optimized"
}
```

使用以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令将区域 API 更新为边缘优化的 API：

```
aws apigateway update-rest-api \
    --rest-api-id a1b2c3 \
    --patch-operations op=replace,path=/endpointConfiguration/types/REGIONAL,value=EDGE
```

由于 [put-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-rest-api.html) 用于更新 API 定义，因此它不适用于更新 API 端点类型。

# API Gateway 中的 REST API 安全策略
<a name="apigateway-security-policies"></a>

*安全策略* 是 API Gateway 提供的最低 TLS 版本和密码套件的预定义组合。当您的客户端与您的 API 或自定义域名建立 TLS 握手时，安全策略会强制实施 API Gateway 接受的 TLS 版本和密码套件。安全策略会保护您的 API 和自定义域名免受网络安全问题的侵扰，例如客户端和服务器之间的篡改和侦听。

API Gateway 支持传统安全策略和增强型安全策略。`TLS_1_0` 和 `TLS_1_2` 是传统安全策略。使用这些安全策略是为了实现向后兼容性。任何以 `SecurityPolicy_` 开头的策略都是增强型安全策略。可将这些策略用于受监管的工作负载、高级治理或后量子密码术。使用增强型安全策略时，还必须设置端点访问模式以进行更多治理。有关更多信息，请参阅 [端点访问模式](#apigateway-security-policies-endpoint-access-mode)。

## API Gateway 如何应用安全策略
<a name="apigateway-security-policies-understanding"></a>

以下示例以 `SecurityPolicy_TLS13_1_3_2025_09` 安全策略为例，显示 API Gateway 如何应用安全策略。

`SecurityPolicy_TLS13_1_3_2025_09` 安全策略接受 TLS 1.3 流量并拒绝 TLS 1.2 和 TLS 1.0 流量。对于 TLS 1.3 流量，该安全策略接受以下密码套件：
+ `TLS_AES_128_GCM_SHA256`
+ `TLS_AES_256_GCM_SHA384`
+ `TLS_CHACHA20_POLY1305_SHA256`

API Gateway 不接受任何其他密码套件。例如，该安全策略将拒绝使用 `AES128-SHA` 密码套件的任何 TLS 1.3 流量。有关受支持的 TLS 版本和密码的更多信息，请参阅[支持的安全策略](apigateway-security-policies-list.md)。

要监控客户端使用哪些 TLS 协议和密码来访问您的 API Gateway，您可以在访问日志中使用 `$context.tlsVersion` 和 `$context.cipherSuite` 上下文变量。有关更多信息，请参阅 [监控 API Gateway 中的 REST API](rest-api-monitor.md)。

## 端点访问模式
<a name="apigateway-security-policies-endpoint-access-mode"></a>

端点访问模式是一个附加参数，对于任何使用以 `SecurityPolicy_` 开头的增强型安全策略的 REST API 或自定义域名，您必须指定该参数。当您创建资源或将安全策略从传统策略更改为增强型策略时，您就会这样做。

将端点访问模式设置为 `STRICT` 时，对您的 REST API 或自定义域名的任何请求都必须通过以下检查：
+ 请求必须源自与您的资源相同的 API Gateway 端点类型。这可能来自区域端点、边缘优化型端点或私有端点。
+ 如果您使用区域或私有端点，API Gateway 将使用 SNI 主机匹配。如果您使用边缘优化型端点，API Gateway 将遵循 CloudFront 的域名前置防护机制。有关更多信息，请参阅[域名前置](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-restrictions)。

如果不满足这两个条件中的任何一个，API Gateway 将会拒绝该请求。建议您尽可能使用 `STRICT` 端点访问模式。

要将现有 API 或域名改为使用严格端点访问模式，请先将您的安全策略更新为增强型安全策略，并将端点访问模式设置为 `BASIC`。验证流量和访问日志后，将端点访问模式设置为 `STRICT`。当您将端点访问模式从 `STRICT` 改为 `BASIC` 时，在传播更改期间，您的端点将在大约 15 分钟内不可用。

对于某些应用程序架构，您不应将端点访问模式设置为 `STRICT`，而应设置为 `BASIC`。下表显示了一些应用程序架构和建议，以便您的 REST API 或自定义域名可以使用 `STRICT` 端点访问模式。


| 架构 | 建议的迁移 | 
| --- | --- | 
| 使用 VPC 端点访问公有自定义域名。 | 此架构使用跨端点类型的流量。建议您迁移到 [API Gateway 中私有 API 的自定义域名](apigateway-private-custom-domains.md)。 | 
|  使用任何方法调用不使用自定义域名或私有 DNS 名称的私有 API。 | 此架构会导致主机标头与 TLS 握手中使用的 SNI 不匹配，并且无法通过 CloudFront 的域名前置限制。建议您将 VPC 迁移到使用私有 DNS。 | 
| 使用域分片将内容分发到多个域或子域。 | 此架构会导致主机标头与 TLS 握手中使用的 SNI 不匹配，并且无法通过 CloudFront 的域名前置限制。建议您使用 `HTTP/2` 并摒弃这种反模式。 | 

以下是使用端点访问模式时的注意事项：
+ 如果 API 或域名的端点访问模式为 `STRICT`，则无法更改端点类型。要更改端点类型，请先将端点访问模式更改为 `BASIC`。
+ 将端点访问模式从 `BASIC` 更改为 `STRICT` 后，API Gateway 会延迟 15 分钟才能强制执行严格的端点访问模式。
+ 当您将安全策略从以 `SecurityPolicy_` 开头的策略更改为传统策略时，必须将端点访问模式取消设置为 `""`。

## 注意事项
<a name="apigateway-security-policies-considerations"></a>

以下是 API Gateway 中针对 REST API 的安全策略的注意事项：
+ 您可以在 OpenAPI 定义文件中导入安全策略。有关更多信息，请参阅 [x-amazon-apigateway-endpoint-access-modex-amazon-apigateway-security-policy](openapi-extensions-security-policy.md)。
+ 您的 API 可以映射到与 API 具有不同安全策略的自定义域名。当您调用该自定义域名时，API Gateway 会使用 API 的安全策略来协商 TLS 握手。如果您禁用默认 API 端点，则这可能会影响调用方调用 API 的方式。
+ 如果您更改安全策略，大约需要 15 分钟才能完成更新。您可以监控您的 API 的 `apiStatus`。当您的 API 更新时，`apiStatus` 为 `UPDATING`，更新完成后，它将变为 `AVAILABLE`。当您的 API 状态为 `UPDATING` 时，您仍然可以调用它。
+ API Gateway 支持对所有 API 应用安全策略。但是，您只能为 REST API 选择安全策略。对于 HTTP 或 WebSocket API，API Gateway 仅支持 `TLS_1_2` 安全策略。
+ 您无法将 API 的安全策略从 `TLS_1_0` 更新为 `TLS_1_2`。
+ 某些安全策略同时支持 ECDSA 和 RSA 密码套件。如果您将此类策略与自定义域名结合使用，则密码套件与客户提供的证书密钥类型（RSA 或 ECDSA）相匹配。如果您将此类策略与 REST API 结合使用，则密码套件将匹配与 RSA 证书类型兼容的密码套件。

# 支持的安全策略
<a name="apigateway-security-policies-list"></a>

下表介绍了可为每种 REST API 端点类型和自定义域名类型指定的[安全策略](apigateway-security-policies.md)。这些策略允许您控制传入连接。API Gateway 仅支持对出站流量使用 TLS 1.2。您可以随时更新 API 或自定义域名的安全策略。

标题中包含 `FIPS` 的策略符合联邦信息处理标准（FIPS），该标准是美国和加拿大政府标准，规定了对保护敏感信息的加密模块的安全要求。要了解更多信息，请参阅 *AWS Cloud 安全性合规性*页面上的[美国联邦信息处理标准（FIPS）140](https://aws.amazon.com/compliance/fips/)。

所有 FIPS 策略均利用 AWS-LC FIPS 验证的加密模块。要了解更多信息，请参阅 *NIST Cryptographic Module Validation Program* 网站上的 [AWS-LC Cryptographic Module](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4631) 页面。

标题中包含 `PQ` 的策略使用[后量子密码术（PQC）](https://aws.amazon.com/security/post-quantum-cryptography/)来实现 TLS 的混合密钥交换算法，以保障流量机密性，抵御未来量子计算带来的安全威胁。

标题中包含 `PFS` 的策略使用[完全正向保密（PFS）](https://en.wikipedia.org/wiki/Forward_secrecy)来确保会话密钥不会泄露。

标题中同时包含 `FIPS` 和 `PQ` 的策略将支持这两项功能。

## 默认安全策略
<a name="apigateway-security-policies-default"></a>

当您创建新的 REST API 或自定义域时，系统会为该资源分配默认安全策略。下表显示这些资源的默认安全策略。


| **资源**： | **默认安全策略名称** | 
| --- | --- | 
| 区域 API | TLS\$11\$10 | 
| 边缘优化的 API | TLS\$11\$10 | 
| 私有 API | TLS\$11\$12 | 
| 区域域 | TLS\$11\$12 | 
| 边缘优化型域名 | TLS\$11\$12 | 
| 私有域 | TLS\$11\$12 | 

## 区域和私有 API 以及自定义域名支持的安全策略
<a name="apigateway-security-policies-non-edge"></a>

下表介绍了可为区域和私有 API 以及自定义域名指定的安全策略：


| **安全策略** | **支持的 TLS 版本** | **支持的密码** | 
| --- | --- | --- | 
| SecurityPolicy\$1TLS13\$11\$13\$12025\$109 | TLS1.3 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$13\$1FIPS\$12025\$109 | TLS1.3 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$12\$1PFS\$1PQ\$12025\$109 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$12\$1PQ\$12025\$109 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| TLS\$11\$12 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| TLS\$11\$10 |  TLS1.3 TLS1.2 TLS1.1 TLS1.0  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 

## 边缘优化型 API 和自定义域名支持的安全策略
<a name="apigateway-security-policies-edge-optimized"></a>

下表介绍了可为边缘优化型 API 和边缘优化型自定义域名指定的安全策略：


| **安全策略名称** | **支持的 TLS 版本** | **支持的密码** | 
| --- | --- | --- | 
| SecurityPolicy\$1TLS13\$12025\$1EDGE | TLS1.3 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS12\$1PFS\$12025\$1EDGE |  TLS1.3 TLS1.2  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS12\$12018\$1EDGE |  TLS1.3 TLS1.2  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| TLS\$11\$10 |  TLS1.3 TLS1.2 TLS1.1 TLS1.0  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 

## OpenSSL 和 RFC 密码名称
<a name="apigateway-secure-connections-openssl-rfc-cipher-names"></a>

OpenSSL 和 IETF RFC 5246 为相同的密码使用不同的名称。下表为每个密码列出了 OpenSSL 名称及对应的 RFC 名称。有关更多信息，请参阅 OpenSSL 文档中的 [ciphers](https://docs.openssl.org/1.1.1/man1/ciphers/)。


| **OpenSSL 密码名称** | **RFC 密码名称** | 
| --- | --- | 
| TLS\$1AES\$1128\$1GCM\$1SHA256 | TLS\$1AES\$1128\$1GCM\$1SHA256 | 
| TLS\$1AES\$1256\$1GCM\$1SHA384 | TLS\$1AES\$1256\$1GCM\$1SHA384 | 
| TLS\$1CHACHA20\$1POLY1305\$1SHA256 | TLS\$1CHACHA20\$1POLY1305\$1SHA256 | 
| ECDHE-RSA-AES128- GCM-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| ECDHE-RSA-AES128-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256  | 
| ECDHE-RSA-AES128-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| ECDHE-RSA-AES256- GCM-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384  | 
| ECDHE-RSA-AES256-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA384  | 
| ECDHE-RSA-AES256-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-GCM-SHA256 | TLS\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| AES256-GCM-SHA384 | TLS\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 | 
| AES128-SHA256 | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 | 
| AES256-SHA | TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-SHA | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| DES-CBC3-SHA | TLS\$1RSA\$1WITH\$13DES\$1EDE\$1CBC\$1SHA | 

# 如何更改安全策略
<a name="apigateway-security-policies-update"></a>

您可以更改 API 的安全策略。如果您通过自定义域名向 API 发送流量，API 和自定义域名无需具有相同的安全策略。当您调用该自定义域名时，API Gateway 会使用 API 的安全策略来协商 TLS 握手。但是，为了保持一致性，建议您对自定义域名和 API 使用相同的安全策略。

如果您更改安全策略，大约需要 15 分钟才能完成更新。您可以监控您的 API 的 `apiStatus`。当您的 API 更新时，`apiStatus` 为 `UPDATING`，更新完成后，它将变为 `AVAILABLE`。当您的 API 正在更新时，您仍然可以调用它。

------
#### [ AWS 管理控制台 ]

**更改 API 的安全策略**

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

1. 选择一个 REST API。

1. 选择 **API 设置**，然后选择**编辑**。

1. 对于**安全策略**，选择一个以 `SecurityPolicy_` 开头的新策略。

1. 对于**端点访问模式**，请选择**严格**。

1. 选择**保存更改**。

   重新部署 API 以使更改生效。由于您已将端点访问模式更改为严格，因此大约需要 15 分钟，更改才能完全传播。

------
#### [ AWS CLI ]

以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令会将 API 更新为使用 `SecurityPolicy_TLS13_1_3_2025_09` 安全策略：

```
aws apigateway update-rest-api \
    --rest-api-id abcd1234 \
    --patch-operations '[
        {
            "op": "replace",
            "path": "/securityPolicy",
            "value": "SecurityPolicy_TLS13_1_3_2025_09"
        }, 
        {
            "op": "replace",
            "path": "/endpointAccessMode",
            "value": "STRICT"
        }
    ]'
```

输出将与以下内容类似：

```
{
    "id": "abcd1234",
    "name": "MyAPI",
    "description": "My API with a new security policy",
    "createdDate": "2025-02-04T11:47:06-08:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "tags": {},
    "disableExecuteApiEndpoint": false,
    "securityPolicy": "SecurityPolicy_TLS13_1_3_2025_09",
    "endpointAccessMode": "STRICT"
    "rootResourceId": "efg456"
}
```

以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令会将使用增强型安全策略的 API 更新为使用 `TLS_1_0` 安全策略。

```
aws apigateway update-rest-api \
    --rest-api-id abcd1234 \
    --patch-operations '[
        {
            "op": "replace",
            "path": "/securityPolicy",
            "value": "TLS_1_0"
        }, 
        {
            "op": "replace",
            "path": "/endpointAccessMode",
            "value": ""
        }
    ]'
```

输出将与以下内容类似：

```
{
    "id": "abcd1234",
    "name": "MyAPI",
    "description": "My API with a new security policy",
    "createdDate": "2025-02-04T11:47:06-08:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "tags": {},
    "disableExecuteApiEndpoint": false,
    "securityPolicy": "TLS_1_0",
    "rootResourceId": "efg456"
}
```

------

# API Gateway 中 REST API 的 IP 地址类型
<a name="api-gateway-ip-address-type"></a>

创建 API 时，您指定可以调用您的 API 的 IP 地址的类型。可以选择 IPv4 来解析 IPv4 地址以调用 API，也可以选择双堆栈以同时支持 IPv4 和 IPv6 地址调用 API。我们建议您将 IP 地址类型设置为双堆栈，以缓解 IP 空间耗尽或保护您的安全状况。有关双堆栈 IP 地址类型的优势的更多信息，请参阅 [IPv6 on AWS](https://docs.aws.amazon.com/whitepapers/latest/ipv6-on-aws/internet-protocol-version-6.html)。

要将 API 限制为仅限 IPv6 流量，您可以创建资源策略，并将源 IP 地址限制为仅限 IPv6 范围。您可以通过更新 API 的配置来更改 IP 地址类型。此更改将立即生效，而您无需重新部署 API。有关更多信息，请参阅 [示例：基于源 IP 地址或范围拒绝 API 流量](apigateway-resource-policies-examples.md#apigateway-resource-policies-source-ip-address-example)。

## IP 地址类型的注意事项
<a name="api-gateway-ip-address-type-considerations"></a>

以下注意事项可能会影响您对 IP 地址类型的使用：
+ 所有区域和边缘优化 API 的默认 IP 地址类型均为 IPv4。
+ 私有 API 只能具有双堆栈 IP 地址类型。
+ 如果您将现有 API 的 IP 地址类型从 IPv4 更改为双堆栈，请确认任何控制 API 访问权限的策略均已更新以考虑 IPv6 调用。更改 IP 地址类型后，更改将立即生效。
+ 如果您将 API 的端点类型从区域或边缘优化迁移到私有，API Gateway 会将 IP 地址类型更改为双堆栈。有关更多信息，请参阅 [在 API Gateway 中更改公有或私有 API 端点类型](apigateway-api-migration.md)。
+ 如果您将 API 的端点类型从私有迁移到区域，则必须将 IP 地址类型设置为双堆栈。端点迁移完成后，您可以将 IP 地址类型更改为 IPv4。有关更多信息，请参阅 [在 API Gateway 中更改公有或私有 API 端点类型](apigateway-api-migration.md)。
+ 您的 API 可以映射到与 API 具有不同 IP 地址类型的自定义域名。如果您禁用默认 API 端点，则这可能会影响调用方调用 API 的方式。
+ 您不能使用外部定义文件来配置 API 的 IP 地址类型。

# 更改 REST API 的 IP 地址类型
<a name="api-gateway-ip-address-type-change"></a>

您可以通过更新 API 的配置来更改 IP 地址类型。您可以使用 AWS 管理控制台、AWS CLI、CloudFormation 或 AWS SDK 更新 API 的配置。如果您更改 API 的 IP 地址类型，您不需要重新部署 API 即可使更改生效。在更改 IP 地址类型之前，请确认任何控制 API 访问权限的策略均已更新以考虑 IPv6 调用。

------
#### [ AWS 管理控制台 ]

**更改 REST API 的 IP 地址类型**

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

1. 选择一个 REST API。

1. 选择 **API 设置**，然后选择**编辑**。

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

1. 选择**保存更改**。

   对 API 配置的更改将立即生效。

------
#### [ AWS CLI ]

以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令将 API 更新为具有双堆栈 IP 地址类型：

```
aws apigateway update-rest-api \
    --rest-api-id abcd1234 \
    --patch-operations "op='replace',path='/endpointConfiguration/ipAddressType',value='dualstack'"
```

输出将与以下内容类似：

```
{
    "id": "abcd1234",
    "name": "MyAPI",
    "description": "My API with a dualstack IP address type",
    "createdDate": "2025-02-04T11:47:06-08:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "tags": {},
    "disableExecuteApiEndpoint": false,
    "rootResourceId": "efg456"
}
```

------

# API Gateway 中用于 REST API 的方法
<a name="how-to-method-settings"></a>

 在 API Gateway 中，API 方法包含[方法请求](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html)和[方法响应](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html)。您可以设置 API 方法以定义客户端提交访问后端服务的请求时应该或必须执行的操作，并定义返回给客户端时收到的响应。对于输入，您可以为客户端选择方法请求参数或适用的负载，以在运行时提供必需或可选的数据。对于输出，您确定将方法响应状态代码、标头和适用的正文作为将后端响应数据映射到的目标，然后再将其返回到客户端。要帮助客户端开发人员理解 API 的行为以及输入和输出格式，您可以[记录 API ](api-gateway-documenting-api.md)并为[无效请求](api-gateway-method-request-validation.md)[提供正确的错误消息](api-gateway-gatewayResponse-definition.md#customize-gateway-responses)。

API 方法请求是 HTTP 请求。要设置方法请求，您需要配置 HTTP 方法（或动词）以及指向 API [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)、标头和适用查询字符串参数的路径。您还可在 HTTP 方法是 `POST`、`PUT` 或 `PATCH` 时配置负载。例如，要使用 [PetStore 示例 API](api-gateway-create-api-from-example.md) 检索宠物，您可以定义 `GET /pets/{petId}` 的 API 方法请求，其中 `{petId}` 是可在运行时获取数字的路径参数。

```
GET /pets/1
Host: apigateway.us-east-1.amazonaws.com
...
```

如果客户端指定了错误的路径，例如 `/pet/1` 或 `/pets/one`，而不是 `/pets/1`，系统就会抛出异常。

API 方法响应是具有指定状态代码的 HTTP 响应。对于非代理集成，您必须设置方法响应以指定映射的必需或可选目标。这些会将集成响应标头或正文转换为关联的方法响应标头或正文。映射可以像[身份转换](https://en.wikipedia.org/wiki/Identity_transform)一样简单，它通过集成按原样传递标头或正文。例如，以下 `200` 方法响应显示了成功按原样传递集成响应的示例。

```
200 OK 
Content-Type: application/json
...

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

原则上，您可以定义对应于来自后端的特定响应的方法响应。通常，这会涉及任何 2XX、4XX 和 5XX 响应。但是，这可能并不可行，因为您通常不可能提前知道后端可能返回的所有响应。实际上，您可以指定一个默认方法响应来处理来自后端的未知响应或未映射的响应。最好将 500 响应指定为默认响应。在任何情况下，您都必须为非代理集成设置至少一个方法响应。否则，API Gateway 将向客户端返回 500 错误响应，即使后端的请求成功也是如此。

 要为 API 支持强类型开发工具包 (如 Java 开发工具包)，您应该为方法请求定义输入数据模型，并为方法响应定义输出数据模型。

## 先决条件
<a name="method-setting-prerequisites"></a>

设置 API 方法之前，请验证以下内容：
+ 方法在 API Gateway 中必须可用。按照中的说明进行操作[教程：使用 HTTP 非代理集成创建 REST API](api-gateway-create-api-step-by-step.md)
+ 如果您希望方法与 Lambda 函数进行通信，则必须已在 IAM 中创建 Lambda 调用角色和 Lambda 执行角色。您还必须创建将在 中与该方法进行通信的 Lambda 函数AWS Lambda 要创建角色和函数，请使用[为 Lambda 非代理集成创建 Lambda 函数](getting-started-lambda-non-proxy-integration.md#getting-started-new-lambda)的[选择 AWS Lambda 集成教程](getting-started-with-lambda-integration.md)中的说明。
+ 如果您希望该方法与 HTTP 或 HTTP 代理集成进行通信，则必须已创建且有权访问将与您的方法进行通信的 HTTP 端点 URL。
+  确认 API Gateway 支持 HTTP 和 HTTP 代理端点的证书。有关详细信息，请参阅 [API Gateway 中的 API Gateway 支持的 HTTP 和 HTTP 代理集成证书的颁发机构](api-gateway-supported-certificate-authorities-for-http-endpoints.md)。

**Topics**
+ [先决条件](#method-setting-prerequisites)
+ [在 API Gateway 中设置方法请求](api-gateway-method-settings-method-request.md)
+ [在 API Gateway 中设置方法响应](api-gateway-method-settings-method-response.md)
+ [使用 API Gateway 控制台设置方法](how-to-set-up-method-using-console.md)

# 在 API Gateway 中设置方法请求
<a name="api-gateway-method-settings-method-request"></a>

设置方法请求涉及在创建 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源之后执行以下任务：

1.  创建新的 API 或选择现有的 API [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)实体。

1.  创建特定于新创建或选定的 API `Resource` 上的 HTTP 动词的 API [方法](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html)资源。此任务可进一步分为以下子任务：
   +  为方法请求添加 HTTP 方法
   +  配置请求参数
   +  定义请求正文的模型
   +  制定授权方案
   +  启用请求验证 

您可以使用以下方法执行这些任务：
+  [API Gateway 控制台](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)
+  AWS CLI 命令 ([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))
+  AWS 开发工具包函数（例如 Node.js 中的 [createResource](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#createResource-property) 和 [putMethod](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#putMethod-property)）
+  API Gateway REST API（[resource:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateResource.html) 和 [method:put](https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html)）。

**Topics**
+ [设置 API 资源](#setup-method-resources)
+ [设置 HTTP 方法](#setup-method-add-http-method)
+ [设置方法请求参数](#setup-method-request-parameters)
+ [设置方法请求模型](#setup-method-request-model)
+ [设置方法请求授权](#setup-method-request-authorization)
+ [设置方法请求验证](#setup-method-request-validation)

## 设置 API 资源
<a name="setup-method-resources"></a>

在 API Gateway API 中，您通过 API [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_GetResources.html)实体树公开可寻址的资源，树的根资源 (`/`) 位于层次结构顶部。根资源相对于 API 的基本 URL，其中包含 API 端点和阶段名称。在 API Gateway 控制台中，该基本 URI 称为**调用 URI**，会在 API 部署后在 API 的阶段编辑器中显示。

API 端点可以是默认主机名或自定义域名。默认主机名采用以下格式：

```
{api-id}.execute-api.{region}.amazonaws.com
```

在此格式中，*\$1api-id\$1* 表示 API Gateway 生成的 API 标识符。`{region}` 变量表示您在创建 API 时选择的 AWS 区域（例如 `us-east-1`）。自定义域名是有效 Internet 域的便于用户识别的任何名称。例如，如果您已经注册 Internet 域 `example.com`，任何 `*.example.com` 都是有效的自定义域名。有关更多信息，请参阅[创建自定义域名](how-to-custom-domains.md)。

对于 [PetStore 示例 API](api-gateway-create-api-from-example.md)，根资源 (`/`) 用于公开 Pet Store。`/pets` 资源表示 Pet Store 中提供的宠物集合。`/pets/{petId}` 公开指定标识符 (`petId`) 的单个宠物。`{petId}` 的路径参数是请求参数的一部分。

要设置 API 资源，您可以选择现有资源作为父资源，然后在此父资源下创建子资源。您开始时将根资源作为父资源，向此父资源添加资源，向这个子资源添加另一个资源作为新的父资源，依此类推，直到添加到其父标识符。然后将命名的资源添加到父资源。

以下 [get-resources](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-resources.html) 命令检索 API 的所有资源：

```
aws apigateway get-resources --rest-api-id apiId
```

对于 PetStore 示例 API，输出将与以下内容类似：

```
{
    "items": [
        {
            "path": "/pets", 
            "resourceMethods": {
                "GET": {}
            }, 
            "id": "6sxz2j", 
            "pathPart": "pets", 
            "parentId": "svzr2028x8"
        }, 
        {
            "path": "/pets/{petId}", 
            "resourceMethods": {
                "GET": {}
            }, 
            "id": "rjkmth", 
            "pathPart": "{petId}", 
            "parentId": "6sxz2j"
        }, 
        {
            "path": "/", 
            "id": "svzr2028x8"
        }
    ]
}
```

每个项目都列出了资源 (`id`) (根资源除外) 的标识符、其直接父级 (`parentId`) 以及资源名称 (`pathPart`)。根资源的特殊之处在于不具有任何父级。选择某个资源作为父资源之后，请使用以下命令添加子资源。

```
aws apigateway create-resource --rest-api-id apiId \
    --parent-id parentId \
    --path-part resourceName
```

例如，在 PetStore 网站上添加要销售的宠物食品时，请使用以下命令：

```
aws apigateway create-resource --rest-api-id a1b2c3 \
    --parent-id svzr2028x8 \
    --path-part food
```

输出将与以下内容类似：

```
{
    "path": "/food", 
    "pathPart": "food", 
    "id": "xdsvhp", 
    "parentId": "svzr2028x8"
}
```

### 使用代理资源来简化 API 设置
<a name="api-gateway-proxy-resource"></a>

随着业务的增长，PetStore 所有者可能决定添加食物、玩具及其他宠物相关的商品进行销售。为此，您可在根资源下添加 `/food`、`/toys` 和其他资源。在每个销售类别下，您可能还需要添加更多资源，例如 `/food/{type}/{item}`、`/toys/{type}/{item}` 等。这很麻烦。如果您决定在资源路径中添加一个中间层 `{subtype}` 以将路径层次结构更改为 `/food/{type}/{subtype}/{item}`、`/toys/{type}/{subtype}/{item}` 等，这些更改将会中断现有的 API 设置。为了避免这种情况，您可以使用 API Gateway [代理资源](api-gateway-set-up-simple-proxy.md)一次性公开一组 API 资源。

API Gateway 将代理资源定义为要在提交请求时指定的资源的占位符。代理资源用 `{proxy+}` 的特殊路径参数表示，该路径通常被称为“贪婪”路径参数。`+` 号表示其附加了哪些子资源。`/parent/{proxy+}` 占位符表示与 `/parent/*` 路径模式匹配的任何资源。您可以使用任意字符串作为贪婪路径参数名称。

以下 [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 命令在根目录下（`/{proxy+}`）创建代理资源：

```
aws apigateway create-resource --rest-api-id apiId \
    --parent-id rootResourceId \
    --path-part {proxy+}
```

输出将与以下内容类似：

```
{
    "path": "/{proxy+}", 
    "pathPart": "{proxy+}", 
    "id": "234jdr", 
    "parentId": "svzr2028x8"
}
```

对于 `PetStore` API 示例，您可以使用 `/{proxy+}` 表示 `/pets` 和 `/pets/{petId}`。此代理资源也可以引用任何其他 (现有或要添加的) 资源，例如 `/food/{type}/{item}`、`/toys/{type}/{item}` 等，或者 `/food/{type}/{subtype}/{item}`、`/toys/{type}/{subtype}/{item}` 等。后端开发人员确定资源层次结构，客户端开发人员负责了解此结构。API Gateway 会将客户端提交的内容传递到后端。

API 可以包含多个代理资源。例如，假设 `/parent/{proxy+}` 与 `/parent/{child}/{proxy+}` 不是同一个父级，API 中支持以下代理资源。

```
/{proxy+}
/parent/{proxy+}
/parent/{child}/{proxy+}
```

如果代理资源具有非代理同级资源，则会从代理资源的表示形式中排除同级资源。在前面的示例中，`/{proxy+}` 是指除 `/parent[/*]` 资源之外的根资源下的任何资源。换言之，针对特定资源的方法请求优先于针对同一资源层次结构级别的通用资源的方法请求。

下表显示了对于 API 的 `prod` 阶段，API Gateway 如何将请求路由到以下资源。

```
ANY /{proxy+}
GET /pets/{proxy+}
GET /pets/dog
```


| 请求 | 选定的路由 | 说明 | 
| --- | --- | --- | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/pets/dog`  |  `GET /pets/dog`  |  请求与此资源完全匹配。  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/pets/cats`  |  `GET /pets/{proxy+}`  |  `/pets/{proxy+}` 贪婪路径变量捕获此请求。  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/animals`  |  `GET /{proxy+}`  |  `/{proxy+}` 贪婪路径变量捕获此请求。  | 

代理资源不能包含任何子资源。`{proxy+}` 后面的任何 API 资源都是冗余和不确定的资源。API 中不允许包含以下代理资源。

```
/{proxy+}/child
/parent/{proxy+}/{child}
/parent/{child}/{proxy+}/{grandchild+}
```

## 设置 HTTP 方法
<a name="setup-method-add-http-method"></a>

API 方法请求通过 API Gateway [方法](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html)资源进行封装。要设置方法请求，您必须先实例化 `Method` 资源，设置至少一个 HTTP 方法和方法的授权类型。

API Gateway 与代理资源密切相关，支持 HTTP 方法 `ANY`。此 `ANY` 方法表示将在运行时提供的任何 HTTP 方法。它允许您将单个 API 方法设置用于 `DELETE`、`GET`、`HEAD`、`OPTIONS`、`PATCH`、`POST` 和 `PUT` 支持的所有 HTTP 方法。

您也可以在非代理资源上设置 `ANY` 方法。通过将 `ANY` 方法与代理资源组合使用，即可获得适用于针对 API 的任何资源所支持的所有 HTTP 方法的单个 API 方法设置。此外，后端可以发展变化，而不会中断现有的 API 设置。

 设置 API 方法之前，请考虑谁可以调用此方法。根据您的计划设置授权类型。对于开放式访问，将其设置为 `NONE`。要使用 IAM 权限，请将授权类型设置为 `AWS_IAM`。要使用 Lambda 授权方函数，请将此属性设置为 `CUSTOM`。要使用 Amazon Cognito 用户池，请将授权类型设置为 `COGNITO_USER_POOLS`。

以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令为 `ANY` 动词创建方法请求，使用 IAM 权限控制其访问权限。

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method ANY \
    --authorization-type AWS_IAM
```

要创建使用不同授权类型的 API 方法请求，请参阅[设置方法请求授权](#setup-method-request-authorization)。

## 设置方法请求参数
<a name="setup-method-request-parameters"></a>

方法请求参数是一种客户端提供完成方法请求所需的输入数据或执行上下文的方式。方法参数可以是路径参数、标头或查询字符串参数。在方法请求设置期间，您必须声明必需的请求参数，使其可供客户端使用。对于非代理集成，您可以将这些请求参数转换为与后端要求兼容的形式。

例如，对于 `GET /pets/{petId}` 方法请求，`{petId}` 路径变量为必需的请求参数。您可在调用 `put-method` 的 AWS CLI 命令时声明此路径参数。以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建带有所需路径参数的方法：

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id rjkmth \
    --http-method GET \
    --authorization-type "NONE" \
    --request-parameters method.request.path.petId=true
```

如果参数不是必需的，则可在 `false` 中将其设置为 `request-parameters`。例如，如果 `GET /pets` 方法使用 `type` 的可选查询字符串参数以及 `age` 的可选标头参数，则您可以使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令声明它们：

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method GET \
    --authorization-type "NONE" \
    --request-parameters method.request.querystring.type=false,method.request.header.age=false
```

如果不使用这种缩写形式，您可以使用 JSON 字符串来设置 `request-parameters` 值：

```
'{"method.request.querystring.type":false,"method.request.header.age":false}'
```

使用此设置，客户端可以按照类型查询宠物：

```
GET /pets?type=dog
```

 客户端可如下所示查询狗狗中的幼犬：

```
GET /pets?type=dog
age:puppy
```

有关如何将方法请求参数映射到集成请求参数的信息，请参阅[针对 API Gateway 中的 REST API 的集成](how-to-integration-settings.md)。

## 设置方法请求模型
<a name="setup-method-request-model"></a>

对于可在负载中获取输入数据的 API 方法，您可以使用模型。模型采用 [JSON 架构草案 4](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) 表示，描述了请求正文的数据结构。借助模型，客户端可以确定如何构建方法请求负载以作为输入。更重要的是，API Gateway 使用模型来[验证请求](api-gateway-method-request-validation.md)、[生成开发工具包](how-to-generate-sdk.md)以及初始化用于在 API Gateway 控制台中设置集成的映射模板。有关如何创建[模型](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html)的信息，请参阅[了解数据模型](models-mappings-models.md)。

根据内容类型，该方法负载可以具有不同格式。模型根据应用负载的媒体类型来编制索引。API Gateway 使用 `Content-Type` 请求标头来确定内容类型。要设置方法请求模型，请在调用 `"media-type":"model-name"` `requestModels` 命令时将 AWS CLI 格式的键/值对添加到 `put-method` 映射。

要使用同一模型而不考虑内容类型，请指定 `$default` 作为键。

例如，对于 PetStore 示例 API，要在 `POST /pets` 方法请求的 JSON 有效载荷上设置模型，您可以调用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令：

```
aws apigateway put-method \
    --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method POST \
    --authorization-type "NONE" \
    --request-models '{"application/json":"petModel"}'
```

其中，`petModel` 是描述宠物的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) 资源的 `Model` 属性值。实际架构定义采用 `schema` 资源的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html#schema](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html#schema) 属性的 JSON 字符串值表示。

 在 Java 或 API 的其他强类型开发工具包中，输入数据将强制转换为派生自架构定义的 `petModel` 类。使用请求模型，生成的开发工具包中的输入数据将强制转换为派生自默认 `Empty` 模型的 `Empty` 类。在这种情况下，客户端无法实例化正确的数据类以提供所需的输入。



## 设置方法请求授权
<a name="setup-method-request-authorization"></a>



 要控制哪些人员可以调用 API 方法，您可在方法中配置[授权类型](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizationType)。您可以使用此类型制定其中一个支持的授权方，包括 IAM 角色和策略 (`AWS_IAM`)、Amazon Cognito 用户池 (`COGNITO_USER_POOLS`) 或 Lambda 授权方 (`CUSTOM`)。

要使用 IAM 权限为 API 方法授予访问权限，请将 `authorization-type` 输入属性设置为 **AWS\$1IAM**。当您设置此选项时，API Gateway 将根据调用方的凭证验证调用方对请求的签名。如果经验证的用户有权调用此方法，它将接受请求。否则，它将拒绝请求，而调用方会收到未经授权的错误响应。除非调用方有权调用 API 方法，否则对该方法的调用不会成功。以下 IAM 策略向调用方授予权限，以调用在同一 AWS 账户中创建的任何 API 方法：

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": "arn:aws:execute-api:*:*:*"
        }
    ]
}
```

------

有关更多信息，请参阅 [使用 IAM 权限控制对 REST API 的访问](permissions.md)。

目前，您只能向 API 所有者的 AWS 账户 内的用户、组和角色授予此策略。来自不同 AWS 账户 的用户只有在被允许代入 API 所有者的 AWS 账户 中的角色并具有调用 `execute-api:Invoke` 操作所需的权限时，才能调用 API 方法。有关跨账户权限的信息，请参阅[使用 IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html)。

您可以使用 AWS CLI、AWS SDK 或 REST API 客户端（例如 [Postman](https://www.postman.com/)），这将实施[签名版本 4（SigV4）签名](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html)。

要使用 Lambda 授权方来授予对 API 方法的访问权限，请将 `authorization-type` 输入属性设置为 `CUSTOM`，并将 [https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId) 输入属性设置为已存在的 Lambda 授权方的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id) 属性值。引用的 Lambda 授权方可以是 `TOKEN` 或 `REQUEST` 类型。有关创建 Lambda 授权方的信息，请参阅 [使用 API Gateway Lambda 授权方](apigateway-use-lambda-authorizer.md)。

要使用 Amazon Cognito 用户池来授予对 API 方法的访问权限，请将 `authorization-type` 输入属性设置为 `COGNITO_USER_POOLS`，并将 [https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId) 输入属性设置为已创建的 `COGNITO_USER_POOLS` 授权方的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id) 属性值。有关创建 Amazon Cognito 用户池授权方的信息，请参阅 [使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问](apigateway-integrate-with-cognito.md)。

## 设置方法请求验证
<a name="setup-method-request-validation"></a>

您可在设置 API 方法请求时启用请求验证。您需要先创建[请求验证程序](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html)。以下 [create-request-validator](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-request-validator.html) 命令创建仅限正文的请求验证程序。

```
aws apigateway create-request-validator \
    --rest-api-id 7zw9uyk9kl \
    --name bodyOnlyValidator \
    --validate-request-body  \
    --no-validate-request-parameters
```

输出将与以下内容类似：

```
{
    "validateRequestParameters": false, 
    "validateRequestBody": true, 
    "id": "jgpyy6", 
    "name": "bodyOnlyValidator"
}
```

您可以使用此请求验证程序，在方法请求设置期间使用请求验证。以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建方法请求，该请求要求传入的请求正文与 `PetModel` 匹配，并且有两个并非必需的请求参数：

```
aws apigateway put-method \
    --rest-api-id 7zw9uyk9kl \
    --resource-id xdsvhp \
    --http-method PUT \
    --authorization-type "NONE" \
    --request-parameters '{"method.request.querystring.type": false, "method.request.querystring.page":false}' \ 
    --request-models '{"application/json":"petModel"}' \
    --request-validator-id jgpyy6
```

要在请求验证中包含某个请求参数，对于请求验证程序，您必须将 `validateRequestParameters` 设置为 `true`，并在 `put-method` 命令中将特定请求参数设置为 `true`。

# 在 API Gateway 中设置方法响应
<a name="api-gateway-method-settings-method-response"></a>

API 方法响应将客户端将收到 API 方法请求的输出进行封装。输出数据包括 HTTP 状态代码、部分标头，还可能包含正文。

使用非代理集成，可从相关的集成响应数据映射指定的响应参数和正文，也可以根据映射分配特定静态值。集成响应中已指定这些映射。映射可以是按原样传递集成响应的恒等变换。

使用代理集成，API Gateway 可自动将后端响应传递到方法响应。您无需设置 API 方法响应。但如果使用 Lambda 代理集成，Lambda 函数必须为 API Gateway 返回[此输出格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format)的结果，才能将集成响应成功映射到方法响应。

通过编程，该方法响应设置相当于创建 API Gateway 的 [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) 资源和设置 [statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#statusCode)、[responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters) 和 [responseModels](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseModels) 的属性。

为 API 方法设置状态代码时，您应该选择一个状态代码作为处理任何意料之外的集成响应的默认代码。将 `500` 设置默认状态代码比较合理，因为这相对于将未映射的响应转换为服务器端错误。出于说明原因，API Gateway 控制台将 `200` 响应设置为默认响应。但您可以将其重置为 `500` 响应。

要设置方法响应，您必须已创建方法请求。

## 设置方法响应状态代码
<a name="setup-method-response-status-code"></a>

方法响应的状态代码定义了响应类型。例如，响应 200、400 和 500 分别表示响应成功、客户端错误和服务器端错误。

要设置方法响应状态代码，请将 [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#statusCode) 属性设置为 HTTP 状态代码。以下 [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) 命令创建 `200` 方法响应。

```
aws apigateway put-method-response \
    --rest-api-id vaz7da96z6 \ 
    --resource-id 6sxz2j \
    --http-method GET \
    --status-code 200
```

## 设置方法响应参数
<a name="setup-method-response-parameters"></a>

方法响应参数定义客户端在哪些标头中收到相关方法请求的响应。响应参数还会根据 API 方法的集成响应中规定的映射指定 API Gateway 将集成响应参数映射到的目标。

要设置方法请求参数，请添加到 `responseParameters` 格式的 `MethodResponse` 键/值对的 [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters) 映射。以下 [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) 命令设置 `my-header` 标头。

```
aws apigateway put-method-response \
        --rest-api-id vaz7da96z6 \
        --resource-id 6sxz2j \
        --http-method GET \
        --status-code 200  \
        --response-parameters method.response.header.my-header=false
```

## 设置方法响应模型
<a name="setup-method-response-models"></a>

 

 方法响应模型定义了方法响应正文的格式。为 API 生成强类型开发工具包时，必须设置方法响应模型。它可确保输出将在 Java 或 Objective-C 中转换为适当的类。在其他情况下，设置模型是可选操作。

设置响应模型之前，必须先在 API Gateway 中创建模型。为此，可以调用 `[create-model](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-model.html)` 命令。以下 [create-model](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-model.html) 命令创建 `PetStorePet` 模型，用于描述对 `GET /pets/{petId}` 方法请求的响应正文。

```
aws apigateway create-model \
    --rest-api-id vaz7da96z6 \
    --content-type application/json \
    --name PetStorePet \
    --schema '{ \
                  "$schema": "http://json-schema.org/draft-04/schema#", \
                  "title": "PetStorePet", \
                  "type": "object", \
                  "properties": { \
                    "id": { "type": "number" }, \
                    "type": { "type": "string" }, \
                    "price": { "type": "number" } \
                  } \
              }'
```

结果将创建为 API Gateway [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) 资源。

要设置方法响应模型以定义有效负载格式，请将 "application/json":"PetStorePet" 密钥值对添加至 [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) 资源的 [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseModels](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseModels) 地图。以下 [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) 命令创建使用响应模型来定义有效载荷格式的方法响应：

```
aws apigateway put-method-response \
    --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method GET \
    --status-code 200  \
    --response-parameters method.response.header.my-header=false \
    --response-models '{"application/json":"PetStorePet"}'
```

# 使用 API Gateway 控制台设置方法
<a name="how-to-set-up-method-using-console"></a>

使用 REST API 控制台创建方法时，您可以同时配置集成请求和方法请求。默认情况下，API Gateway 会为您的方法创建 `200` 方法响应。

以下说明介绍如何编辑方法请求设置，以及如何为您的方法创建其它方法响应。

**Topics**
+ [在 API Gateway 控制台中编辑 API Gateway 方法请求](#how-to-method-settings-callers-console)
+ [使用 API Gateway 控制台设置 API Gateway 方法响应](#how-to-method-response-settings-console)

## 在 API Gateway 控制台中编辑 API Gateway 方法请求
<a name="how-to-method-settings-callers-console"></a>

 这些说明假设您已创建了方法请求。有关如何创建方法的更多信息，请参阅[使用 API Gateway 控制台设置 API 集成请求](how-to-method-settings-console.md)。

1. 在**资源**窗格中，选择方法，然后选择**方法请求**选项卡。

1. 在**方法请求设置**部分中，选择**编辑**。

1. 对于**授权**，选择一个可用的授权方。

   1. 要为任何用户启用对此方法的开放式访问，请选择**无**。如果未更改默认设置，则可跳过此步骤。

   1. 要使用 IAM 权限来控制客户端对方法的访问权限，请选择 `AWS_IAM`。如果选择此选项，只允许具有已附加正确 IAM 策略的 IAM 角色的用户调用此方法。

      要创建 IAM 角色，请指定类似于以下格式的访问策略：

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

****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "execute-api:Invoke"
            ],
            "Resource": [
              "arn:aws:execute-api:us-east-1:111111111111:aaabbb/*/GET/"
            ]
          }
        ]
      }
      ```

------

      在此访问策略中，`arn:aws:execute-api:us-east-1:111111111111:aaabbb/*/GET/` 是方法的 ARN。您可以通过在**资源**页面上选择方法来找到该方法的 ARN。有关设置 IAM 权限的更多信息，请参阅[使用 IAM 权限控制对 REST API 的访问](permissions.md)。

      要创建 IAM 角色，您可以调整以下教程中的说明：[为 Lambda 非代理集成创建 Lambda 函数](getting-started-lambda-non-proxy-integration.md#getting-started-new-lambda)。

   1.  要使用 Lambda 授权方，请选择令牌或请求授权方。创建 Lambda 授权方，让此选择显示在下拉菜单中。有关如何创建 Lambda 授权方的信息，请参阅 [使用 API Gateway Lambda 授权方](apigateway-use-lambda-authorizer.md)。

   1.  要使用 Amazon Cognito 用户池，请在 **Cognito 用户池授权方**下选择可用的用户池。在 Amazon Cognito 中创建一个用户群体，并在 API Gateway 中创建一个 Amazon Cognito 用户群体授权方，以便在下拉菜单中显示此选择。有关如何创建 Amazon Cognito 用户池授权方的信息，请参阅 [使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问](apigateway-integrate-with-cognito.md)。

1.  要指定请求验证，请从**请求验证程序**下拉菜单中选择一个值。要关闭请求验证，请选择**无**。有关各选项的更多信息，请参阅[针对 API Gateway 中的 REST API 的请求验证](api-gateway-method-request-validation.md)。

1. 选择**需要 API 密钥**以需要 API 密钥。启用后，将在[使用计划](api-gateway-api-usage-plans.md)中使用 API 密钥以限制客户端流量。

1. （可选）要在 API Gateway 生成的此 API 的 Java SDK 中分配操作名称，请为**输入名称**输入一个名称。例如，对于 `GET /pets/{petId}` 的方法请求，相对应的默认 Java 开发工具包操作名称为 `GetPetsPetId`。此名称由此方法的 HTTP 动词 (`GET`) 和资源路径变量名称 (`Pets` 和 `PetId`) 构建而成。如果您将操作名称设置为 `getPetById`，开发工具包操作名称将变为 `GetPetById`。

1. 要向方法中添加查询字符串参数，请执行以下操作：

   1. 选择 **URL 查询字符串参数**，然后选择**添加查询字符串**。

   1. 对于**名称**，输入查询字符串参数的名称。

   1. 如果要将新创建的查询字符串参数用于请求验证，请选择**必填**。有关请求验证的更多信息，请参阅[针对 API Gateway 中的 REST API 的请求验证](api-gateway-method-request-validation.md)。

   1. 如果要将新创建的查询字符串参数用作缓存密钥的一部分，请选中**缓存**。有关缓存的更多信息，请参阅 [将方法或集成参数用作索引缓存响应的缓存键](api-gateway-caching.md#enable-api-gateway-cache-keys)。

   要移除查询字符串参数，请选择**移除**。

1. 要向方法中添加标头参数，请执行以下操作：

   1. 选择 **HTTP 请求标头**，然后选择**添加标头**。

   1. 对于**名称**，输入标头的名称。

   1. 如果要将新创建的标头用于请求验证，请选择**必填**。有关请求验证的更多信息，请参阅[针对 API Gateway 中的 REST API 的请求验证](api-gateway-method-request-validation.md)。

   1. 如果要将新创建的标头用作缓存密钥的一部分，请选中**缓存**。有关缓存的更多信息，请参阅 [将方法或集成参数用作索引缓存响应的缓存键](api-gateway-caching.md#enable-api-gateway-cache-keys)。

   要移除标头，请选择**移除**。

1.  要声明包含 `POST`、`PUT` 或 `PATCH` HTTP 动词的方法请求的负载格式，请选择**请求正文**，然后执行以下操作：

   1. 选择**添加模型**。

   1. 对于**内容类型**，输入 MIME 类型（例如 `application/json`）。

   1. 对于**模型**，请从下拉菜单中选择一个模型。该 API 目前可用的模型包括默认 `Empty` 和 `Error` 模型以及您创建和添加到 API 的[模型](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html)集合的任何模型。有关创建模型的更多信息，请参阅[针对 REST API 的数据模型](models-mappings-models.md)。
**注意**  
 模型适用于向客户端通知预期数据格式的负载。这对生成骨骼映射模板非常有帮助。请务必使用 Java、C \$1、Objective-C 和 Swift 等语言编程生成 API 的强类型开发工具包。仅在已针对负载启用请求验证时才需要该开发工具包。

1. 选择**保存**。

## 使用 API Gateway 控制台设置 API Gateway 方法响应
<a name="how-to-method-response-settings-console"></a>

 API 方法可以有一个或多个响应。每个响应都通过 HTTP 状态代码编制索引。默认情况下，API Gateway 控制台将 `200` 响应添加到方法响应。您可以对其进行修改，例如让该方法返回 `201`。还可以添加其他响应，例如添加 `409` 表示拒绝访问，添加 `500` 表示所用的阶段变量未初始化。

 要使用 API Gateway 控制台修改、删除或添加对 API 方法的响应，请按照以下说明操作。

1. 在**资源**窗格中，选择方法，然后选择**方法响应**选项卡。您可能需要选择右箭头按钮，以显示该选项卡。

1. 在**方法响应设置**部分，选择**创建响应**。

1. 对于 **HTTP 状态代码**，输入 HTTP 状态代码，例如`200`、`400` 或 `500`。

    如果后端返回的响应未定义相应的方法响应，API Gateway 就无法将响应返回给客户端。而是返回 `500 Internal server error` 错误响应。

1. 选择**添加标头**。

1.  对于**标头名称**，输入名称。

    要将标头从后端返回给客户端，请在方法响应中添加标头。

1.  选择**添加模型**以定义方法响应正文的格式。

   为**内容类型**输入响应负载的媒体类型，然后从**模型**下拉菜单中选择模型。

1. 选择**保存**。

要修改现有响应，请导航到您的方法响应，然后选择**编辑**。要更改 **HTTP 状态代码**，请选择**删除**并创建新的方法响应。

对于从后端返回的每个响应，您必须将兼容的响应配置为方法响应。但配置方法响应标头和负载模型是可选的，除非您先将后端的结果映射到方法响应，然后再返回给客户端。此外，如果您要为 API 生成强类型开发工具包，方法响应负载模型就非常重要。

# 在 API Gateway 中控制和管理对 REST API 的访问
<a name="apigateway-control-access-to-api"></a>

API Gateway 支持多种用于控制和管理对 API 的访问的机制：

您可以使用以下机制进行身份验证和授权：
+ **资源策略**允许您创建基于资源的策略，以允许或拒绝从指定的源 IP 地址或 VPC 终端节点访问您的 API 和方法。有关更多信息，请参阅 [使用 API Gateway 资源策略控制对 API 的访问](apigateway-resource-policies.md)。
+ **标准的AWS IAM 角色和策略**提供可应用于整个 API 集或各个方法的灵活且可靠的访问控制。可以使用 IAM 角色和策略来控制哪些人可以创建和管理您的 API，以及谁可以调用它们。有关更多信息，请参阅 [使用 IAM 权限控制对 REST API 的访问](permissions.md)。
+ **IAM 标签** 可与 IAM 策略结合使用来控制访问权限。有关更多信息，请参阅 [使用标签控制对 API Gateway REST API 资源的访问](apigateway-tagging-iam-policy.md)。
+ **接口 VPC 终端节点的终端节点策略**允许您将 IAM 资源策略附加到接口 VPC 终端节点，用于改进[私有 API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html) 的安全性。有关更多信息，请参阅 [在 API Gateway 中为私有 API 使用 VPC 端点策略](apigateway-vpc-endpoint-policies.md)。
+ **Lambda 授权方** 是 Lambda 函数，它们使用持有者令牌身份验证以及由标头、路径、查询字符串、阶段变量或上下文变量请求参数描述的信息来控制对 REST API 方法的访问。Lambda 授权方用于控制谁可以调用 REST API 方法。有关更多信息，请参阅 [使用 API Gateway Lambda 授权方](apigateway-use-lambda-authorizer.md)。
+ **Amazon Cognito 用户池** 可让您为 REST API 创建可自定义的身份验证和授权解决方案。Amazon Cognito 用户池用于控制谁可以调用 REST API 方法。有关更多信息，请参阅 [使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问](apigateway-integrate-with-cognito.md)。

您可以使用以下机制执行与访问控制相关的其他任务：
+ **跨源资源共享 (CORS)** 可让您控制您的 REST API 响应跨域资源请求的方式。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 的 CORS](how-to-cors.md)。
+ **客户端 SSL 证书** 可用于验证发送到后端系统的 HTTP 请求是否来自 API Gateway。有关更多信息，请参阅 [生成和配置 SSL 证书以用于 API Gateway 中的后端身份验证](getting-started-client-side-ssl-authentication.md)。
+ **AWS WAF** 可用于保护您的 API Gateway API 免受常见 Web 漏洞攻击。有关更多信息，请参阅 [在 API Gateway 中使用 AWS WAF 保护 REST API](apigateway-control-access-aws-waf.md)。

您可以使用以下机制跟踪和限制您已向授权客户端授予的访问权限：
+ **使用计划** 可让您向客户提供 **API 密钥**，然后跟踪和限制每个 API 密钥的 API 阶段和方法的使用。有关更多信息，请参阅 [API Gateway 中针对 REST API 的使用计划和 API 密钥](api-gateway-api-usage-plans.md)。

# 使用 API Gateway 资源策略控制对 API 的访问
<a name="apigateway-resource-policies"></a>

Amazon API Gateway *资源策略*是您附加到 API 的 JSON 策略文档，用于控制指定的主体（通常是 IAM 角色或组）能否调用 API。您可以使用 API Gateway 资源策略来允许 API 安全地被以下对象调用：
+ 指定的 AWS 账户中的用户
+ 指定源 IP 地址范围或 CIDR 块
+ 指定的 Virtual Private Cloud (VPC) 或 VPC 端点（在任何账户中）。

您可以使用 AWS 管理控制台、AWS CLI 或 AWS SDK，为 API Gateway 中的任何 API 端点类型附加资源策略。对于 [私有 API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html)，您可以将资源策略与 VPC 端点策略一起使用，控制委托人有权访问哪些资源和操作。有关更多信息，请参阅 [在 API Gateway 中为私有 API 使用 VPC 端点策略](apigateway-vpc-endpoint-policies.md)。

 API Gateway 资源策略与基于 IAM 身份的策略不同。基于 IAM 身份的策略附加到 IAM 用户、组或角色并定义这些身份能够对哪些资源执行哪些操作。API Gateway 资源策略是附加到资源的。您可以同时使用 API Gateway 资源策略和 IAM 策略。有关更多信息，请参阅[基于身份的策略和基于资源的策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)。

**Topics**
+ [Amazon API Gateway 的访问策略语言概述](apigateway-control-access-policy-language-overview.md)
+ [API Gateway 资源策略如何影响授权工作流程](apigateway-authorization-flow.md)
+ [API Gateway 资源策略示例](apigateway-resource-policies-examples.md)
+ [创建 API Gateway 资源策略并将其附加到 API](apigateway-resource-policies-create-attach.md)
+ [AWS可在 API Gateway 资源策略中使用的 条件键](apigateway-resource-policies-aws-condition-keys.md)

# Amazon API Gateway 的访问策略语言概述
<a name="apigateway-control-access-policy-language-overview"></a>

本页介绍 Amazon API Gateway 资源策略中使用的基本元素。

指定资源策略所用的语法与 IAM 策略相同。如需全面了解策略语言，请参阅 *IAM 用户指南*中的 [IAM 策略概述](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)和 [AWS Identity and Access Management 策略参考](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html)。

有关 AWS 服务如何决定是应允许还是拒绝指定请求的更多信息，请参阅[决定是允许还是拒绝请求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow)。

## 访问策略中的常用元素
<a name="apigateway-common-elements-in-an-access-policy"></a>

就其最基本的意义而言，资源策略包含以下元素：
+ **资源** – API 是您能够允许或拒绝权限的 Amazon API Gateway 资源。在策略中，使用 Amazon Resource Name (ARN) 标识资源。您还可以使用缩写语法，当您保存资源策略时，API Gateway 会自动将其扩展为完整的 ARN。要了解更多信息，请参阅“[API Gateway 资源策略示例](apigateway-resource-policies-examples.md)”。

  有关完整 `Resource` 元素的格式，请参阅 [在 API Gateway 中执行 API 的权限的 Resource 格式](api-gateway-control-access-using-iam-policies-to-invoke-api.md#api-gateway-iam-policy-resource-format-for-executing-api)。
+ **操作** – 对于每个资源，Amazon API Gateway 支持一组操作。您可使用操作关键字标识允许（或拒绝）的资源操作。

  例如，`execute-api:Invoke` 权限将允许在客户端请求时调用 API 的用户权限。

  有关 `Action` 元素的格式，请参阅[在 API Gateway 中执行 API 的权限的 Action 格式](api-gateway-control-access-using-iam-policies-to-invoke-api.md#api-gateway-iam-policy-action-format-for-executing-api)。
+ **效果** – 当用户请求特定操作（可以是 `Allow` 或 `Deny`）时的效果。您也可显式拒绝对资源的访问，这样可确保用户无法访问该资源，即使有其他策略授予了访问权限的情况下也是如此。
**注意**  
“隐式拒绝”与“默认拒绝”相同。  
“隐式拒绝”与“明确拒绝”不同。有关更多信息，请参阅[“默认拒绝”与“显式拒绝”的区别](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#AccessPolicyLanguage_Interplay)。
+ **主体** – 允许访问语句中的操作和资源的账户或用户。在资源策略中，主体是接收此权限的用户或账户。

下面的资源策略示例展示了上述常用策略元素。该策略向其源 IP 地址位于地址块 *123.4.5.6/24* 内的任何用户授予对指定 *region* 中的指定 *account-id* 下的 API 的访问权限。如果用户的源 IP 不在该范围内，该策略将拒绝对 API 的所有访问。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "123.4.5.6/24"
                }
            }
        }
    ]
}
```

------

# API Gateway 资源策略如何影响授权工作流程
<a name="apigateway-authorization-flow"></a>

当 API Gateway 评估附加到您的 API 的资源策略时，结果会受到您为 API 定义的身份验证类型的影响，如以下章节的流程图所示。

**Topics**
+ [仅限 API Gateway 资源策略](#apigateway-authorization-flow-resource-policy-only)
+ [Lambda 授权方和资源策略](#apigateway-authorization-flow-lambda)
+ [IAM 身份验证和资源策略](#apigateway-authorization-flow-iam)
+ [Amazon Cognito 身份验证和资源策略](#apigateway-authorization-flow-cognito)
+ [策略评估结果表](#apigateway-resource-policies-iam-policies-interaction)

## 仅限 API Gateway 资源策略
<a name="apigateway-authorization-flow-resource-policy-only"></a>

在此工作流中，API Gateway 资源策略附加至 API，但没有为 API 定义任何身份验证类型。对策略的评估将涉及根据调用方的入站标准寻求明确的许可。隐式拒绝或任何明确拒绝都将导致拒绝调用方。

![\[仅资源策略的授权流程。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/apigateway-auth-resource-policy-only.png)


以下是此类资源策略的一个示例。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:api-id/",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}
```

------

## Lambda 授权方和资源策略
<a name="apigateway-authorization-flow-lambda"></a>

在此工作流程中，除了资源策略外，还为 API 配置了 Lambda 授权方。将在两个阶段中对资源策略进行评估。在调用 Lambda 授权方之前，API Gateway 首先评估策略并检查是否存在任何明确拒绝。一经发现，将立即拒绝调用方访问。否则，会调用 Lambda 授权方，它将返回[策略文档](api-gateway-lambda-authorizer-output.md)，对该文档与资源策略进行评估。如果授权方使用缓存，则 API Gateway 可能会返回缓存的策略文档。结果根据[表 A](#apigateway-resource-policies-iam-policies-interaction) 确定。

以下示例资源策略仅允许从 VPC 端点调用，其 VPC 端点 ID 为 `vpce-1a2b3c4d`。在“预身份验证”评估期间，只有来自示例中所述的 VPC 端点的调用才允许向前推进并评估 Lambda 授权方。阻止所有剩余的调用。如果为私有 API 使用自定义域名，则此授权工作流程相同。

![\[资源策略和 Lambda 授权方的授权流程。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/apigateway-auth-lambda-resource-policy.png)


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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:us-east-1:111111111111:api-id/"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
}
```

------

## IAM 身份验证和资源策略
<a name="apigateway-authorization-flow-iam"></a>

在此工作流中，除资源策略外，还为 API 配置 IAM 身份验证。使用 IAM 服务对用户进行身份验证后，API 将同时评估附加到用户的策略以及资源策略。结果因调用方是在同一 AWS 账户 中还是在与 API 所有者不同的 AWS 账户 中而异。

如果调用方和 API 所有者来自不同的账户，则 IAM policy 和资源策略都明确允许调用方继续操作。有关更多信息，请参阅[表 B](#apigateway-resource-policies-iam-policies-interaction)。

然而，如果调用方和 API 所有者在同一 AWS 账户中，则 IAM 用户策略或资源策略必须明确允许调用方继续操作。有关更多信息，请参阅[表 A](#apigateway-resource-policies-iam-policies-interaction)。

![\[资源策略和 Lambda 身份验证的授权流程。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/apigateway-auth-iam-resource-policy.png)


以下是跨账户资源策略的一个示例。假定 IAM policy 包含允许效果，此资源策略将仅允许来自 VPC ID 为 `vpc-2f09a348` 的 VPC 的调用。有关更多信息，请参阅[表 B](#apigateway-resource-policies-iam-policies-interaction)。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:us-east-1:111111111111:api-id/"
            ],
            "Condition" : {
                "StringEquals": {
                    "aws:SourceVpc": "vpc-2f09a348"
                    }
            }
        }
    ]
}
```

------

## Amazon Cognito 身份验证和资源策略
<a name="apigateway-authorization-flow-cognito"></a>

在此工作流程中，除了资源策略之外，还为 API 配置了 [Amazon Cognito 用户池](apigateway-integrate-with-cognito.md)。API Gateway 首先尝试通过 Amazon Cognito 对调用方进行身份验证。这通常通过调用方提供的 [JWT 令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)执行。如果身份验证成功，则资源策略将被独立评估，且需要显示允许。拒绝或“不允许也不拒绝”将导致拒绝。下面是资源策略的一个示例，可以与 Amazon Cognito 用户池一起使用。

![\[资源策略和 Amazon Cognito 授权方的授权流程。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/apigateway-auth-cognito-resource-policy.png)


下面是资源策略的一个示例，该策略只允许从指定的源 IP 调用（假定 Amazon Cognito 身份验证令牌包含允许）。有关更多信息，请参阅[表 B](#apigateway-resource-policies-iam-policies-interaction)。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:api-id/",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}
```

------

## 策略评估结果表
<a name="apigateway-resource-policies-iam-policies-interaction"></a>

表 A 列出了对 API Gateway API 的访问由 IAM 策略（或 Lambda 授权方）和 API Gateway 资源策略（两者都位于同一 AWS 账户中）控制时产生的行为。


| **IAM 策略（或 Lambda 授权方）** | **API Gateway 资源策略** | **产生的行为** | 
| --- | --- | --- | 
| 允许 | 允许 | 允许 | 
| 允许 | 既不允许也不拒绝 | 允许 | 
| 允许 | 拒绝 | 显式拒绝 | 
| 既不允许也不拒绝 | 允许 | 允许 | 
| 既不允许也不拒绝 | 既不允许也不拒绝 | 隐式拒绝 | 
| 既不允许也不拒绝 | 拒绝 | 显式拒绝 | 
| 拒绝 | 允许 | 显式拒绝 | 
| 拒绝 | 既不允许也不拒绝 | 显式拒绝 | 
| 拒绝 | 拒绝 | 显式拒绝 | 

表 B 列出了对 API Gateway API 的访问由 IAM 策略（或 Amazon Cognito 用户池授权方）和 API Gateway 资源策略（两者位于不同 AWS 账户中）控制时产生的行为。如果其中一个静默（既不允许也不拒绝），则跨账户访问会被拒绝。这是因为跨账户访问要求资源策略和 IAM 策略（或 Amazon Cognito 用户池授权方）均明确授予访问权限。


| **IAM 策略（或 Amazon Cognito 用户池授权方）** | **API Gateway 资源策略** | **产生的行为** | 
| --- | --- | --- | 
| 允许 | 允许 | 允许 | 
| 允许 | 既不允许也不拒绝 | 隐式拒绝 | 
| 允许 | 拒绝 | 显式拒绝 | 
| 既不允许也不拒绝 | 允许 | 隐式拒绝 | 
| 既不允许也不拒绝 | 既不允许也不拒绝 | 隐式拒绝 | 
| 既不允许也不拒绝 | 拒绝 | 显式拒绝 | 
| 拒绝 | 允许 | 显式拒绝 | 
| 拒绝 | 既不允许也不拒绝 | 显式拒绝 | 
| 拒绝 | 拒绝 | 显式拒绝 | 

# API Gateway 资源策略示例
<a name="apigateway-resource-policies-examples"></a>

此页面介绍 API Gateway 资源策略的几个典型使用案例。

以下示例策略使用简化语法来指定 API 资源。此简化语法是一种缩写方式，通过这种方式，您可以引用 API 资源，而不指定完整的 Amazon Resource Name (ARN)。当您保存策略时，API Gateway 会将缩写语法转换为完整 ARN。例如，您可以在资源策略中指定资源 `execute-api:/stage-name/GET/pets`。当您保存资源策略时， API Gateway 会将资源转换为 `arn:aws:execute-api:us-east-2:123456789012:aabbccddee/stage-name/GET/pets`。API Gateway 使用当前区域、您的AWS账户 ID 以及与资源策略关联的 REST API 的 ID 来构建完整的 ARN。您可以使用 `execute-api:/*` 来表示当前 API 中的所有阶段、方法和路径。有关访问策略语言的更多信息，请参阅[Amazon API Gateway 的访问策略语言概述](apigateway-control-access-policy-language-overview.md)。

**Topics**
+ [示例：允许另一个 AWS 账户中的角色使用 API](#apigateway-resource-policies-cross-account-example)
+ [示例：基于源 IP 地址或范围拒绝 API 流量](#apigateway-resource-policies-source-ip-address-example)
+ [示例：使用私有 API 时，基于源 IP 地址或范围拒绝 API 流量](#apigateway-resource-policies-source-ip-address-vpc-example)
+ [示例：允许基于源 VPC 或 VPC 端点的私有 API 流量](#apigateway-resource-policies-source-vpc-example)

## 示例：允许另一个 AWS 账户中的角色使用 API
<a name="apigateway-resource-policies-cross-account-example"></a>

以下示例资源策略通过[签名版本 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）协议，将一个 AWS 账户中的 API 访问权限授予位于另一个 AWS 账户中的两个角色。具体而言，向由 `account-id-2` 标识的 AWS 账户的开发人员和管理员角色授予了 `execute-api:Invoke` 操作权限，允许他们对您 AWS 账户中的 `pets` 资源（API）执行 `GET` 操作。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111122223333:role/developer",
                    "arn:aws:iam::111122223333:role/Admin"
                ]
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/stage/GET/pets"
            ]
        }
    ]
}
```

------

## 示例：基于源 IP 地址或范围拒绝 API 流量
<a name="apigateway-resource-policies-source-ip-address-example"></a>

以下资源策略示例拒绝（阻止）从两个指定源 IP 地址块向 API 传入流量。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
               "execute-api:/*"
            ],
            "Condition" : {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}
```

------

如果您使用任何 IAM 用户策略或 API Gateway 资源策略来控制对 API Gateway 或任何 API Gateway API 的访问权限，请确认您的策略已更新为包含 IPv6 地址范围。当客户端开始使用双堆栈端点时，未更新为处理 IPv6 地址的策略可能会影响客户端对 API Gateway 的访问权限。有关更多信息，请参阅 [在 IAM 策略中使用 IPv6 地址](api-ref.md#api-reference-service-endpoints-dualstack-iam)。

## 示例：使用私有 API 时，基于源 IP 地址或范围拒绝 API 流量
<a name="apigateway-resource-policies-source-ip-address-vpc-example"></a>

以下资源策略示例拒绝（阻止）两个指定源 IP 地址块向私有 API 传入流量。使用私有 API 时，`execute-api` VPC 端点重新写入原始源 IP 地址。`aws:VpcSourceIp` 条件根据原始请求方 IP 地址筛选请求。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
               "execute-api:/*"
            ],
            "Condition" : {
                "IpAddress": {
                    "aws:VpcSourceIp": ["192.0.2.0/24", "198.51.100.0/24"]
                }
            }
        }
    ]
}
```

------

## 示例：允许基于源 VPC 或 VPC 端点的私有 API 流量
<a name="apigateway-resource-policies-source-vpc-example"></a>

以下示例资源策略允许仅从指定的 Virtual Private Cloud (VPC) 或 VPC 端点传入到私有 API 的流量。

此示例资源策略指定源 VPC：

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                   "aws:SourceVpc": "vpc-1a2b3c4d"
                }
            }
        }
    ]
}
```

------

此示例资源策略指定源 VPC 端点：

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
}
```

------

# 创建 API Gateway 资源策略并将其附加到 API
<a name="apigateway-resource-policies-create-attach"></a>

要允许用户通过调用 API 执行服务访问您的 API，您必须创建 API Gateway 资源策略，并将该策略附加到 API。当您将策略附加到 API 时，它会将该策略中的权限应用于 API 中的方法。如果您更新资源策略，您将需要部署 API。

**Topics**
+ [先决条件](#apigateway-resource-policies-prerequisites)
+ [将资源策略附加到 API Gateway API](#apigateway-resource-policies-create-attach-procedure)
+ [排除资源策略故障](#apigateway-resource-policies-troubleshoot)

## 先决条件
<a name="apigateway-resource-policies-prerequisites"></a>

 要更新 API Gateway 资源策略，您将需要 `apigateway:UpdateRestApiPolicy` 权限和 `apigateway:PATCH` 权限。

对于边缘优化的 API 或区域 API，您可以在创建 API 时或者在部署 API 后，将资源策略附加到该 API。对于私有 API，如果没有资源策略，就无法部署 API。有关更多信息，请参阅 [API Gateway 中的私有 REST API](apigateway-private-apis.md)。

## 将资源策略附加到 API Gateway API
<a name="apigateway-resource-policies-create-attach-procedure"></a>

以下过程说明如何将资源策略附加到 API Gateway API。

------
#### [ AWS 管理控制台 ]

**将资源策略附加到 API Gateway API**

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

1. 选择一个 REST API。

1. 在主导航窗格中，选择**资源策略**。

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

1. （可选）选择**选择模板**以生成示例策略。

   在策略示例中，占位符括在双大括号 (`"{{placeholder}}"`) 内。将每个占位符（包括大括号）替换为必要的信息。

1. 如果您没有使用任何一个模板示例，则输入您的资源策略。

1. 选择**保存更改**。

如果先前已在 API Gateway 控制台中部署了 API，则需要重新进行部署以使资源策略生效。

------
#### [ AWS CLI ]

要使用 AWS CLI 创建新的 API 并向其附加资源策略，请使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令：

```
aws apigateway create-rest-api \
    --name "api-name" \
    --policy "{\"jsonEscapedPolicyDocument\"}"
```

要使用 AWS CLI 将资源策略附加到现有 API，请使用以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令：

```
aws apigateway update-rest-api \
    --rest-api-id api-id \
    --patch-operations op=replace,path=/policy,value='"{\"jsonEscapedPolicyDocument\"}"'
```

也可以将资源策略作为单独的 `policy.json` 文件附加，并将其包含在 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令中。使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建具有资源策略的新 API：

```
aws apigateway create-rest-api \
    --name "api-name" \
    --policy file://policy.json
```

`policy.json` 是一项 API Gateway 资源策略，例如[示例：基于源 IP 地址或范围拒绝 API 流量](apigateway-resource-policies-examples.md#apigateway-resource-policies-source-ip-address-example)。

------
#### [ AWS CloudFormation ]

您可以使用 CloudFormation 通过资源策略创建 API。以下示例使用示例资源策略[示例：基于源 IP 地址或范围拒绝 API 流量](apigateway-resource-policies-examples.md#apigateway-resource-policies-source-ip-address-example)创建 REST API。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: testapi
      Policy:
        Statement:
          - Action: 'execute-api:Invoke'
            Effect: Allow
            Principal: '*'
            Resource: 'execute-api:/*'
          - Action: 'execute-api:Invoke'
            Effect: Deny
            Principal: '*'
            Resource: 'execute-api:/*'
            Condition:
              IpAddress: 
                'aws:SourceIp': ["192.0.2.0/24", "198.51.100.0/24" ]
        Version: 2012-10-17		 	 	 
  Resource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'helloworld'
  MethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref Resource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: MOCK
        RequestTemplates:
          application/json: '{"statusCode": 200}'
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: '{}'
      MethodResponses:
        - StatusCode: 200
          ResponseModels:
            application/json: 'Empty'
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - MethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: test
```

------

## 排除资源策略故障
<a name="apigateway-resource-policies-troubleshoot"></a>

以下故障排除指南可能有助于解决资源策略问题。

### 我的 API 返回 \$1"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:\$1\$1\$1\$1\$1\$1\$1\$1/\$1\$1\$1\$1/\$1\$1\$1\$1/"\$1
<a name="apigateway-resource-policies-troubleshoot-auth"></a>

在资源策略中，如果您将主体设置为 AWS 主体，如下所示：

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111111111111:role/developer",
                    "arn:aws:iam::111111111111:role/Admin"
                ]
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/stage/GET/pets"
            ]
        }
    ]
}
```

------

您必须对 API 中的每个方法使用 `AWS_IAM` 授权，否则 API 会返回之前的错误消息。有关如何为方法开启 `AWS_IAM` 授权的更多说明，请参阅 [API Gateway 中用于 REST API 的方法](how-to-method-settings.md)。

### 我的资源策略未更新
<a name="apigateway-resource-policies-troubleshoot-deploy"></a>

 如果在创建 API 后更新资源策略，您将需要附加更新的策略，然后部署 API 以传播更改。单独更新或保存策略不会更改 API 的运行时行为。有关部署 API 的更多信息，请参阅[在 API Gateway 中部署 REST API。](how-to-deploy-api.md)。

### 我的资源策略返回以下错误：策略文档无效。请检查策略语法并确保主体有效。
<a name="apigateway-resource-policies-troubleshoot-invalid-principal"></a>

要纠正此错误，我们首先建议您检查策略语法。有关更多信息，请参阅 [Amazon API Gateway 的访问策略语言概述](apigateway-control-access-policy-language-overview.md)。我们还建议您检查指定的所有主体是否有效且未被删除。

此外，如果您的 API 位于某个[选择加入的区域](https://docs.aws.amazon.com/glossary/latest/reference/glos-chap.html?icmpid=docs_homepage_addtlrcs#optinregion)，请确认资源政策中的所有账户都启用了该区域。

# AWS可在 API Gateway 资源策略中使用的 条件键
<a name="apigateway-resource-policies-aws-condition-keys"></a>

下表包含可针对每种授权类型，可在 API Gateway 中的 API 资源策略中使用的AWS条件键。

有关这些AWS条件键的更多信息，请参阅[AWS全局条件上下文键](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html)。


| **条件键**： | **标准** | **是否需要 `AuthN`？** | **授权类型** | 
| --- | --- | --- | --- | 
| aws:CurrentTime | 无 | 否 | All | 
| aws:EpochTime | 无 | 否 | All | 
| aws:TokenIssueTime | 键仅在使用临时安全凭证签名的请求中存在。 | 是 | IAM | 
| aws:MultiFactorAuthPresent | 键仅在使用临时安全凭证签名的请求中存在。 | 是 | IAM | 
| aws:MultiFactorAuthAge | 键仅在请求中存在 MFA 时存在。 | 是 | IAM | 
| aws:PrincipalAccount | 无 | 是 | IAM | 
| aws:PrincipalArn | 无 | 是 | IAM | 
| aws:PrincipalOrgID | 仅在委托人是组织成员时，才将此键包含在请求上下文中。 | 是 | IAM | 
| aws:PrincipalOrgPaths | 仅在委托人是组织成员时，才将此键包含在请求上下文中。 | 是 | IAM | 
| aws:PrincipalTag | 仅在委托人使用具有附加标签的 IAM 用户时，才将此键包含在请求上下文中。对于委托人，如果使用附加了标签或会话标签的 IAM 角色，则应包括它。 | 是 | IAM | 
| aws:PrincipalType | 无 | 是 | IAM | 
| aws:Referer | 键仅在调用方在 HTTP 标头中提供了值时存在。 | 否 | All | 
| aws:SecureTransport | 无 | 否 | All | 
| aws:SourceArn | 无 | 否 | All | 
| aws:SourceIp | 无 | 否 | All | 
| aws:SourceVpc | 此键只能用于私有 API。 | 否 | All | 
| aws:SourceVpce | 此键只能用于私有 API。 | 否 | All | 
| aws:VpcSourceIp | 此键只能用于私有 API。 | 否 | All | 
| aws:UserAgent | 键仅在调用方在 HTTP 标头中提供了值时存在。 | 否 | All | 
| aws:userid | 无 | 是 | IAM | 
| aws:username | 无 | 是 | IAM | 

# 使用 IAM 权限控制对 REST API 的访问
<a name="permissions"></a>

 通过控制对以下两个 API Gateway 组件进程的访问，您可以使用 [IAM 权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_controlling.html)控制对 Amazon API Gateway API 的访问：
+  要在 API Gateway 中创建、部署和管理 API，您必须授予 API 开发人员相关权限，使其可执行受 API Gateway 的 API 管理组件支持的必要操作。
+  要调用已部署的 API 或者刷新 API 缓存，您必须授予 API 调用方相应权限，使其可执行受 API Gateway 的 API 执行组件支持的必要 IAM 操作。

 对此两个进程的访问控制将采用两种不同的许可模型，我们将在下文进行说明。

## 用于创建和管理 API 的 API Gateway 权限模型
<a name="api-gateway-control-access-iam-permissions-model-for-managing-api"></a>

 要使 API 开发人员可在 API Gateway 中创建和管理 API，您必须[创建 IAM 权限策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html)，允许特定的 API 开发人员创建、更新、部署、查看或删除必要的 [API 实体](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)。将权限策略附加到用户、角色或组。

要提供访问权限，请为您的用户、组或角色添加权限：
+ AWS IAM Identity Center 中的用户和群组：

  创建权限集合。按照《AWS IAM Identity Center 用户指南》**中[创建权限集](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html)的说明进行操作。
+ 通过身份提供商在 IAM 中托管的用户：

  创建适用于身份联合验证的角色。按照《IAM 用户指南》**中[针对第三方身份提供商创建角色（联合身份验证）](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html)的说明进行操作。
+ IAM 用户：
  + 创建您的用户可以担任的角色。按照《IAM 用户指南》**中[为 IAM 用户创建角色](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html)的说明进行操作。
  + （不推荐使用）将策略直接附加到用户或将用户添加到用户组。按照《IAM 用户指南》**中[向用户添加权限（控制台）](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console)中的说明进行操作。

有关如何使用此许可模型的更多信息，请参阅 [API Gateway 基于身份的策略](security_iam_service-with-iam.md#security_iam_service-with-iam-id-based-policies)。

## 用于调用 API 的 API Gateway 权限模型
<a name="api-gateway-control-access-iam-permissions-model-for-calling-api"></a>

要使 API 调用方可调用 API 或刷新其缓存，您必须创建相关的 IAM policy，以允许指定的 API 调用方调用已启用用户身份验证的 API 方法。API 开发人员可将该方法的 `authorizationType` 属性设置为 `AWS_IAM`，以要求调用方提交用户的凭证以进行身份验证。API Gateway 支持使用签名版本 4a（SigV4a）和签名版本 4（SigV4）来验证用户的凭证。有关更多信息，请参阅 [AWS 签名版本 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html)。然后，将该策略附加到您的用户、角色或组。

在此 IAM 权限策略语句中，IAM `Resource` 元素包含一系列已部署的 API 方法，并使用给定的 HTTP 动词和 API Gateway [资源路径](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)进行识别。IAM `Action` 元素包含必要的 API Gateway API 执行操作。这些操作包括 `execute-api:Invoke` 或 `execute-api:InvalidateCache`，其中 `execute-api` 表示 API Gateway 的底层 API 执行组件。

有关如何使用此许可模型的更多信息，请参阅 [针对调用 API 的访问控制](api-gateway-control-access-using-iam-policies-to-invoke-api.md)。

 当 API 在后端集成AWS服务（例如 AWS Lambda）时，API Gateway 还必须具有代表 API 调用方访问集成的AWS资源（例如，调用 Lambda 函数）的许可。要授予这些权限，请创建**适用于 API Gateway 的AWS服务**类型的 IAM 角色。当您在 IAM 管理控制台中创建该角色时，生成的角色包含以下 IAM 信任策略，该策略声明 API Gateway 为可信实体，允许其代入该角色：

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

****  

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

------

如果您通过调用 [create-role](https://docs.aws.amazon.com/cli/latest/reference/iam/create-role.html) CLI 命令或相应的开发工具包方法创建 IAM 角色，则必须提供以上信任策略作为 `assume-role-policy-document` 的输入参数。请勿试图直接在 IAM 管理控制台中创建这样的策略，或调用 AWS CLI [create-policy](https://docs.aws.amazon.com/cli/latest/reference/iam/create-policy.html) 命令或相应的开发工具包方法创建这样的策略。

要让 API Gateway 调用集成的AWS服务，您还必须为此角色附加适用于调用集成的AWS服务的 IAM 权限策略。例如，要调用 Lambda 函数，您必须在 IAM 角色中包含以下 IAM 权限策略：

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

****  

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

------

请注意，Lambda 支持结合了信任策略和权限策略这两者的基于资源的标准访问策略。当使用 API Gateway 控制台集成 API 与 Lambda 函数时，系统不会明确要求您设置此 IAM 角色，因为控制台会经您同意，对 Lambda 函数设置基于资源的权限。

**注意**  
 要制定对 AWS 服务的访问控制，您可以使用基于调用方的权限模型，将权限策略直接附加到调用方的用户或组；或者使用基于角色的权限模型，将权限策略附加到 API Gateway 可代入的 IAM 角色。在两种模型中的许可策略可能有所不同。例如，当基于调用方的策略可阻止访问时，基于角色的策略可能会允许访问。您可以利用这一点来要求用户仅通过 API Gateway API 访问 AWS 服务。

# 针对调用 API 的访问控制
<a name="api-gateway-control-access-using-iam-policies-to-invoke-api"></a>

在此部分中，您将了解使用 IAM 权限控制对 API 的访问的权限模型。启用 IAM 授权后，客户端必须使用签名版本 4a（SigV4a）和签名版本 4（SigV4），才能使用 AWS 凭证签署其请求。有关更多信息，请参阅 [AWS 签名版本 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html)。

在本节中，我们介绍模板 IAM 策略语句和策略语句参考。策略语句参考包括与 API 执行服务相关的 `Action` 和 `Resource` 字段的格式。使用这些参考可创建您的 IAM 策略语句。在创建 IAM 策略语句时，您可能需要考虑 API Gateway 资源策略会给授权工作流程带来哪些影响。有关更多信息，请参阅 [API Gateway 资源策略如何影响授权工作流程](apigateway-authorization-flow.md)。

对于私有 API，您应使用 API Gateway 资源策略和 VPC 终端节点策略的组合。有关更多信息，请参阅以下主题：
+ [使用 API Gateway 资源策略控制对 API 的访问](apigateway-resource-policies.md)
+ [在 API Gateway 中为私有 API 使用 VPC 端点策略](apigateway-vpc-endpoint-policies.md)

## 控制谁可以使用 IAM 策略调用 API Gateway API 方法
<a name="api-gateway-who-can-invoke-an-api-method-using-iam-policies"></a>

 要控制谁可以或不可以使用 IAM 权限调用已部署的 API，请创建一个包含必要权限的 IAM 策略文档。此类策略文档的模板如下所示。

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Permission",
      "Action": [
        "execute-api:Execution-operation"           
      ],
      "Resource": [
        "arn:aws:execute-api:region:123456789012:api-id/stage/METHOD_HTTP_VERB/Resource-path"
      ]
    }
  ]
}
```

------

 此处，`Permission` 将被替换为 `Allow` 或 `Deny`，具体取决于您是要授予或撤消相应权限。`Execution-operation` 将被替换为受 API 执行服务支持的操作。`METHOD_HTTP_VERB` 表示受指定资源支持的 HTTP 动词。`Resource-path` 是已部署的 API `[Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)` 实例的 URL 路径占位符，该实例可支持上述的 `METHOD_HTTP_VERB`。有关更多信息，请参阅 [在 API Gateway 中执行 API 的 IAM 策略的语句参考](#api-gateway-calling-api-permissions)。

**注意**  
要使 IAM 策略生效，您必须已通过将该方法的 `AWS_IAM` 属性设置为 `[authorizationType](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizationType)` 对 API 方法启用 IAM 身份验证。否则，这些 API 方法会从外部进行访问。

 例如，要授予某个用户查看特定 API 提供的宠物列表的权限，同时拒绝该用户向列表添加宠物的权限，您可以在 IAM 策略中包含以下语句：

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:111111111111:api-id/*/GET/pets"
      ]
    },
    {
      "Effect": "Deny",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:111111111111:api-id/*/POST/pets"
      ]
    }
  ]
}
```

------

要授予某个用户查看配置为 `GET /pets/{petId}` 的 API 提供的某个特定宠物的权限，您可以在 IAM 策略中包含以下语句：

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "arn:aws:execute-api:us-east-1:111122223333:api-id/*/GET/pets/a1b2"
            ]
        }
    ]
}
```

------

## 在 API Gateway 中执行 API 的 IAM 策略的语句参考
<a name="api-gateway-calling-api-permissions"></a>

以下信息将介绍用于执行 API 的访问权限的 IAM 策略语句的 Action 和 Resource 格式。

### 在 API Gateway 中执行 API 的权限的 Action 格式
<a name="api-gateway-iam-policy-action-format-for-executing-api"></a>

API 执行的 `Action` 表达式有以下一般格式：

```
execute-api:action
```

其中 *action* 是一项可用的 API 执行操作：
+ **\$1**，代表以下所有操作。
+ **Invoke (调用)**，用于根据客户端请求调用 API。
+ **InvalidateCache**，用于根据客户端请求使 API 缓存失效。

### 在 API Gateway 中执行 API 的权限的 Resource 格式
<a name="api-gateway-iam-policy-resource-format-for-executing-api"></a>

API 执行的 `Resource` 表达式有以下一般格式：

```
arn:aws:execute-api:region:account-id:api-id/stage-name/HTTP-VERB/resource-path-specifier
```

其中：
+ *region* 为 AWS 区域（例如，适用于所有 **us-east-1** 区域的 **\$1** 或 AWS），与该方法已部署的 API 相对应。
+ *account-id* 是 REST API 所有者的 12 位 AWS 账户 ID。
+ *api-id* 是 API Gateway 为该方法分配给 API 的标识符。
+ *stage-name* 是与方法关联的阶段的名称。
+ *HTTP-VERB* 是该方法的 HTTP 动词。它可以是以下任一动词：GET、POST、PUT、DELETE、PATCH。
+ *resource-path-specifier* 是前往预期方法的路径。

**注意**  
如果您指定了通配符 (`*`)，则 `Resource` 表达式会将通配符应用于表达式的其余部分。

一些示例资源表达式包括：
+ **arn:aws:execute-api:\$1:\$1:\$1**，适用于任何 AWS 区域内任何 API 的任何阶段中的任何资源路径。
+ **arn:aws:execute-api:us-east-1:\$1:\$1**，适用于 AWS 的任何 `us-east-1` 区域内任何 API 的任何阶段中的任何资源路径。
+ **arn:aws:execute-api:us-east-1:\$1:*api-id*/\$1**，适用于AWS区域 us-east-1 内带 *api-id* 标识符的 API 中任何阶段的任何资源路径。
+ **arn:aws:execute-api:us-east-1:\$1:*api-id*/`test`/\$1**，适用于 AWS 区域 us-east-1 内带 *api-id* 标识符的 API 中 `test` 阶段的任何资源路径。

要了解更多信息，请参阅“[API Gateway Amazon 资源名称 (ARN) 参考](arn-format-reference.md)”。

# API 执行权限的 IAM 策略示例
<a name="api-gateway-iam-policy-examples-for-api-execution"></a>

有关许可模型和其他背景信息，请参阅 [针对调用 API 的访问控制](api-gateway-control-access-using-iam-policies-to-invoke-api.md)。

以下策略语句将为带 `a123456789` 标识符的 API 授予在 `test` 阶段沿 `mydemoresource` 路径调用任何 POST 方法的用户权限，并假定已将相应的 API 部署至AWS区域 us-east-1：

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:*:a123456789/test/POST/my-demo-resource-path/*"
      ]
    }
  ]
}
```

------

以下示例策略语句将在已部署相应 API 的任何 `petstorewalkthrough/pets` 区域为带 `a123456789` 标识符的 API 授予在任何阶段沿 AWS 资源路径调用任意方法的用户许可：

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:*:*:a123456789/*/*/petstorewalkthrough/pets"
      ]
    }
  ]
}
```

------

# 在 API Gateway 中为私有 API 使用 VPC 端点策略
<a name="apigateway-vpc-endpoint-policies"></a>

要提高私有 API 的安全性，您可以创建 VPC 端点策略。VPC 端点策略是一种 IAM 资源策略，您可以将其附加到接口端点。有关更多信息，请参阅[使用 VPC 端点控制对服务的访问](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html)。

您可能需要创建 VPC 端点策略来执行以下任务：
+ 仅允许某些组织或资源访问您的 VPC 端点和调用您的 API。
+ 使用单一策略，并避免使用基于会话或基于角色的策略，来控制 API 的流量。
+ 从本地迁移到 AWS 时，加强应用程序的安全边界。

## VPC 端点策略注意事项
<a name="apigateway-vpc-endpoint-policies-considerations"></a>

以下是 VPC 端点策略的注意事项：
+ 根据 `Authorization` 标头值评估调用方的身份。首先评估 VPC 端点策略，然后 API Gateway 根据在方法请求中配置的授权类型对请求进行评估。下表显示了如何根据 `Authorization` 标头值的内容评估 VPC 端点策略。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-vpc-endpoint-policies.html)
+ 如果访问控制依赖于使用持有者令牌，例如 Lambda 或 Amazon Cognito 授权方，则可以使用[资源的属性](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resource-properties)来控制安全边界。
+  如果授权控制使用 IAM 授权，则可以使用[资源的属性](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resource-properties)和[主体的属性](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resource-principal)来控制安全边界。
+ VPC 端点策略可以与 API Gateway 资源策略一起使用。API Gateway 资源策略指定哪些主体可以访问 API。端点策略指定了谁可以访问 VPC，以及可以从 VPC 端点调用哪些 API。您的私有 API 需要资源策略，但您不需要创建自定义 VPC 端点策略。

## VPC 端点策略示例
<a name="apigateway-vpc-endpoint-policies-examples"></a>

您可以为 Amazon API Gateway 创建 Amazon Virtual Private Cloud 端点策略，并在其中指定以下内容：
+ 可执行操作的主体。
+ 可执行的操作。
+ 可用于执行操作的资源。

这可能取决于授权标头的内容。有关更多信息，请参阅 [VPC 端点策略注意事项](#apigateway-vpc-endpoint-policies-considerations)。有关其它策略示例，请参阅 GitHub 网站上的 [Data perimeter policy examples](https://github.com/aws-samples/data-perimeter-policy-examples)。

要将策略附加到 VPC 端点，您需要使用 VPC 控制台。有关更多信息，请参阅[使用 VPC 端点控制对服务的访问](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html)。

## 示例 1：授予对两个 API 的访问权限的 VPC 端点策略
<a name="apigateway-vpc-endpoint-policies-example-1"></a>

以下示例策略只授予通过该策略附加到的 VPC 端点访问两个特定 API。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Principal": "*",
            "Action": [
                "execute-api:Invoke"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:execute-api:us-east-1:123412341234:a1b2c3d4e5/*",
                "arn:aws:execute-api:us-east-1:123412341234:aaaaa11111/*"
            ]
        }
    ]
}
```

------

## 示例 2：授予对 GET 方法的访问权限的 VPC 端点策略
<a name="apigateway-vpc-endpoint-policies-example-2"></a>

以下示例策略授予用户通过该策略附加到的 VPC 端点访问特定 API 的 `GET` 方法。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Principal": "*",
            "Action": [
                "execute-api:Invoke"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:execute-api:us-east-1:123412341234:a1b2c3d4e5/stageName/GET/*"
            ]
        }
    ]
}
```

------

## 示例 3：授予用户对特定 API 的特定用户访问权限的 VPC 端点策略
<a name="apigateway-vpc-endpoint-policies-example-3"></a>

以下示例策略授予特定用户通过该策略附加到的 VPC 端点访问特定 API。

在这种情况下，因为策略限制了对特定 IAM 主体的访问权限，所以您必须将方法的 `authorizationType` 设置为 `AWS_IAM` 或 `NONE`。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Principal": {
                "AWS": [
                    "arn:aws:iam::123412341234:user/MyUser"
                ]
            },
            "Action": [
                "execute-api:Invoke"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:execute-api:us-east-1:123412341234:a1b2c3d4e5/*"
            ]
        }
    ]
}
```

------

## 示例 4：VPC 端点策略授予用户对特定自定义域名以及映射到该域的每个 API 的访问权限
<a name="apigateway-vpc-endpoint-policies-example-4"></a>

以下示例策略通过该策略附加到的 VPC 端点，向用户授予对私有 API 的特定自定义域名的访问权限。通过此策略，只要用户在 VPC 端点与自定义域名之间创建了域名访问关联，并且用户被授予了调用自定义域名以及映射到自定义域名的任何私有 API 的权限，用户就可以调用映射到此自定义域名的任何 API。有关更多信息，请参阅 [API Gateway 中私有 API 的自定义域名](apigateway-private-custom-domains.md)。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
      "Resource": [
        "*"
      ],
       "Condition": {
        "ArnEquals": {
          "execute-api:viaDomainArn": "arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.test.com+f4g5h6",
        }
      }
    }
  ]
}
```

------

## 示例 5：VPC 端点策略授予或拒绝对特定 API 和域资源的访问权限
<a name="apigateway-vpc-endpoint-policies-example-5"></a>

以下示例策略向用户授予对特定 API 和域资源的访问权限。通过此策略，只要用户在 VPC 端点与自定义域名之间创建了域名访问关联，并且用户被授予了调用自定义域名以及映射到自定义域名的任何私有 API 的权限，用户就可以调用允许的私有 API 和域资源。有关更多信息，请参阅 [API Gateway 中私有 API 的自定义域名](apigateway-private-custom-domains.md)。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
      "Resource": [
        "arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.test.com+f4g5h6",
        "arn:aws:execute-api:us-west-2:111122223333:a1b2c3d4e5/*"
      ]
    },
    {
      "Effect": "Deny",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
      "Resource": [
        "arn:aws:execute-api:us-west-2:111122223333:a1b2c3d4e5/admin/*",
        "arn:aws:execute-api:us-west-2:111122223333:bcd123455/*"
      ]
    }
  ]
}
```

------

## 示例 6：VPC 端点策略按属于组织的主体和资源授予或拒绝访问权限
<a name="apigateway-vpc-endpoint-policies-example-6"></a>

以下示例策略向属于某个组织的主体和资源授予访问权限。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Condition": {
                "StringEquals": {
                    "aws:ResourceOrgID": "o-abcd1234",
                    "aws:PrincipalOrgID": "o-abcd1234"
                }
            },
            "Action": "*",
            "Resource": "*",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Sid": "AllowRequestsByOrgsIdentitiesToOrgsResources"
        }
    ]
}
```

------

# 在 API Gateway 中使用标签控制对 REST API 的访问
<a name="apigateway-control-access-tags"></a>

使用 IAM 策略中基于属性的访问控制，可以微调访问 REST API 的权限。

有关更多信息，请参阅 [使用标签控制对 API Gateway REST API 资源的访问](apigateway-tagging-iam-policy.md)。

# 使用 API Gateway Lambda 授权方
<a name="apigateway-use-lambda-authorizer"></a>

使用 *Lambda 授权方*（以前称为*自定义授权方*）控制对 API 的访问。当客户端提出对 API 方法的请求时，API Gateway 会调用 Lambda 授权方。Lambda 授权方将调用方的身份作为输入，并返回 IAM 策略作为输出。

使用 Lambda 授权方实施自定义授权方案。该方案可以使用请求参数来确定调用方的身份或使用持有者令牌身份验证策略（例如 OAuth 或 SAML）。在 API Gateway REST API 控制台中、使用 AWS CLI 或 AWS SDK 创建 Lambda 授权方。

## Lambda 授权方授权工作流
<a name="api-gateway-lambda-authorizer-flow"></a>

下图展示了 Lambda 授权方的授权工作流。

![\[API Gateway Lambda 授权工作流\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/custom-auth-workflow.png)


**API Gateway Lambda 授权工作流**

1. 客户端对 API Gateway API 调用方法，以传递持有者令牌或请求参数。

1. API Gateway 检查是否为方法请求配置了 Lambda 授权方。如果已配置，API Gateway 将调用 Lambda 函数。

1. Lambda 函数会对调用方进行身份验证。该函数可通过以下方式进行身份验证：
   + 调用 OAuth 提供程序来获取 OAuth 访问令牌。
   + 调用 SAML 提供程序来获取 SAML 断言。
   + 基于请求参数值生成 IAM 策略。
   + 从数据库中检索凭证。

1. Lambda 函数返回一个 IAM 策略和一个主体标识符。如果 Lambda 函数不返回该信息，表明调用失败。

1. API Gateway 会对 IAM 策略进行评估。
   + 如果拒绝访问，API Gateway 将返回一个合适的 HTTP 状态代码，如 `403 ACCESS_DENIED`。
   + 如果允许访问，API Gateway 将调用该方法。

     如果启用了授权缓存，API Gateway 将缓存策略，这样就不会再次调用 Lambda 授权方函数。确保策略适用于 API 中的所有资源和方法。

您可以自定义 `403 ACCESS_DENIED` 或 `401 UNAUTHORIZED` 网关响应。要了解更多信息，请参阅[针对 API Gateway 中 REST API 的网关响应](api-gateway-gatewayResponse-definition.md)。

## 选择 Lambda 授权方类型
<a name="api-gateway-lambda-authorizer-choose"></a>

Lambda 授权方有两种类型：

**基于请求参数的 Lambda 授权方（`REQUEST` 授权方）**  
`REQUEST` 授权方以标头、查询字符串参数、[`stageVariables`](api-gateway-mapping-template-reference.md#stagevariables-template-reference) 和 [`$context`](api-gateway-mapping-template-reference.md#context-variable-reference) 变量的组合接收调用方的身份。您可以使用 `REQUEST` 授权方，根据来自多个身份来源（例如 `$context.path` 和 `$context.httpMethod` 上下文变量）的信息创建精细策略。  
如果您为 `REQUEST` 授权方开启授权缓存，API Gateway 会验证请求中是否存在所有指定的身份来源。如果指定的身份来源缺失、为 null 或为空，API Gateway 将返回 `401 Unauthorized` HTTP 响应，而不调用 Lambda 授权方函数。如果定义了多个身份来源，它们都将用于派生授权方的缓存键并保持相应顺序。您可以使用多个身份来源定义精细缓存键。  
如果您更改缓存键的任意部分并重新部署 API，授权方将丢弃缓存策略文档并生成新的文档。  
如果您为 `REQUEST` 授权方关闭授权缓存，API Gateway 会直接将请求传递给 Lambda 函数。

**基于令牌的 Lambda 授权方（`TOKEN` 授权方）**  
`TOKEN` 授权方接收持有者令牌（例如 JSON Web 令牌（JWT）或 OAuth 令牌）中的调用方身份。  
如果您为 `TOKEN` 授权方开启授权缓存，令牌来源中指定的标头名称将成为缓存键。  
此外，您还可以使用令牌验证来输入正则表达式语句。API Gateway 将针对此表达式执行输入令牌的初始验证并在成功验证后调用 Lambda 授权方函数。这有助于减少对您的 API 的调用。  
仅 `TOKEN` 授权方支持 `IdentityValidationExpression` 属性。有关更多信息，请参阅 [x-amazon-apigateway-authorizer 对象](api-gateway-swagger-extensions-authorizer.md)。

**注意**  
建议您使用 `REQUEST` 授权方来控制对 API 的访问。使用 `REQUEST` 授权方时，您可以基于多个身份来源控制对 API 的访问，而使用 `TOKEN` 授权方时则基于单一身份来源。此外，您还可以使用 `REQUEST` 授权方的多个身份来源分离缓存键。

## `REQUEST` 授权方 Lambda 函数示例
<a name="api-gateway-lambda-authorizer-request-lambda-function-create"></a>

以下代码示例创建一个 Lambda 授权方函数，如果客户端提供的 `HeaderAuth1` 标头、`QueryString1` 查询参数和 `StageVar1` 阶段变量都分别与 `headerValue1`、`queryValue1` 和 `stageValue1` 的指定值相匹配，该函数将允许调用请求。

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

```
// A simple request-based authorizer example to demonstrate how to use request 
// parameters to allow or deny a request. In this example, a request is  
// authorized if the client-supplied HeaderAuth1 header, QueryString1
// query parameter, and stage variable of StageVar1 all match
// specified values of 'headerValue1', 'queryValue1', and 'stageValue1',
// respectively.
    
export const handler = function(event, context, callback) {
    console.log('Received event:', JSON.stringify(event, null, 2));
    
    // Retrieve request parameters from the Lambda function input:
    var headers = event.headers;
    var queryStringParameters = event.queryStringParameters;
    var pathParameters = event.pathParameters;
    var stageVariables = event.stageVariables;
        
    // Parse the input for the parameter values
    var tmp = event.methodArn.split(':');
    var apiGatewayArnTmp = tmp[5].split('/');
    var awsAccountId = tmp[4];
    var region = tmp[3];
    var restApiId = apiGatewayArnTmp[0];
    var stage = apiGatewayArnTmp[1];
    var method = apiGatewayArnTmp[2];
    var resource = '/'; // root resource
    if (apiGatewayArnTmp[3]) {
        resource += apiGatewayArnTmp[3];
    }
        
    // Perform authorization to return the Allow policy for correct parameters and 
    // the 'Unauthorized' error, otherwise.

     
    if (headers.HeaderAuth1 === "headerValue1"
        && queryStringParameters.QueryString1 === "queryValue1"
        && stageVariables.StageVar1 === "stageValue1") {
        callback(null, generateAllow('me', event.methodArn));
    }  else {
        callback(null, generateDeny('me', event.methodArn));
    }
}
     
// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    // Required output:
    var authResponse = {};
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; // default version
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}
     
var generateAllow = function(principalId, resource) {
    return generatePolicy(principalId, 'Allow', resource);
}
     
var generateDeny = function(principalId, resource) {
    return generatePolicy(principalId, 'Deny', resource);
}
```

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

```
# A simple request-based authorizer example to demonstrate how to use request
# parameters to allow or deny a request. In this example, a request is
# authorized if the client-supplied headerauth1 header, QueryString1
# query parameter, and stage variable of StageVar1 all match
# specified values of 'headerValue1', 'queryValue1', and 'stageValue1',
# respectively.

def lambda_handler(event, context):
    print(event)

    # Retrieve request parameters from the Lambda function input:
    headers = event['headers']
    queryStringParameters = event['queryStringParameters']
    pathParameters = event['pathParameters']
    stageVariables = event['stageVariables']

    # Parse the input for the parameter values
    tmp = event['methodArn'].split(':')
    apiGatewayArnTmp = tmp[5].split('/')
    awsAccountId = tmp[4]
    region = tmp[3]
    restApiId = apiGatewayArnTmp[0]
    stage = apiGatewayArnTmp[1]
    method = apiGatewayArnTmp[2]
    resource = '/'

    if (apiGatewayArnTmp[3]):
        resource += apiGatewayArnTmp[3]

    # Perform authorization to return the Allow policy for correct parameters
    # and the 'Unauthorized' error, otherwise.

    if (headers['HeaderAuth1'] == "headerValue1" and queryStringParameters['QueryString1'] == "queryValue1" and stageVariables['StageVar1'] == "stageValue1"):
        response = generateAllow('me', event['methodArn'])
        print('authorized')
        return response
    else:
        print('unauthorized')
        response = generateDeny('me', event['methodArn'])
        return response
    # Help function to generate IAM policy


def generatePolicy(principalId, effect, resource):
    authResponse = {}
    authResponse['principalId'] = principalId
    if (effect and resource):
        policyDocument = {}
        policyDocument['Version'] = '2012-10-17'
        policyDocument['Statement'] = []
        statementOne = {}
        statementOne['Action'] = 'execute-api:Invoke'
        statementOne['Effect'] = effect
        statementOne['Resource'] = resource
        policyDocument['Statement'] = [statementOne]
        authResponse['policyDocument'] = policyDocument

    authResponse['context'] = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": True
    }

    return authResponse


def generateAllow(principalId, resource):
    return generatePolicy(principalId, 'Allow', resource)


def generateDeny(principalId, resource):
    return generatePolicy(principalId, 'Deny', resource)
```

------

在此示例中，Lambda 授权方函数将检查输入参数并按如下所示操作：
+ 如果所有必需的参数值匹配预期值，该授权方函数将返回 `200 OK` HTTP 响应和 IAM 策略（类似于以下内容）并且方法请求成功：

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

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/"
      }
    ]
  }
  ```

------
+ 否则，授权方函数将返回 `401 Unauthorized` HTTP 响应并且方法请求将失败。

除了返回 IAM 策略之外，Lambda 授权方函数还必须返回调用方的委托人标识符。它还可以选择返回一个 `context` 对象，其中包含可传入集成后端的其他信息。有关更多信息，请参阅 [来自 API Gateway Lambda 授权方的输出](api-gateway-lambda-authorizer-output.md)。

在生产代码中，您可能需要先对用户进行身份验证，然后才能授予授权。您可以通过调用身份验证提供程序，在 Lambda 函数中添加身份验证逻辑，如该提供程序的文档中的指示。

## `TOKEN` 授权方 Lambda 函数示例
<a name="api-gateway-lambda-authorizer-token-lambda-function-create"></a>

以下代码示例创建一个 `TOKEN` Lambda 授权方函数，如果客户端提供的令牌值为 `allow`，该函数将允许调用方调用方法。如果令牌值为 `deny`，则不允许调用方调用请求。如果令牌值为 `unauthorized` 或空字符串，该授权方函数将返回 `401 UNAUTHORIZED` 响应。

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

```
// A simple token-based authorizer example to demonstrate how to use an authorization token 
// to allow or deny a request. In this example, the caller named 'user' is allowed to invoke 
// a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke 
// the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty
// string, the authorizer function returns an HTTP 401 status code. For any other token value, 
// the authorizer returns an HTTP 500 status code. 
// Note that token values are case-sensitive.

export const handler =  function(event, context, callback) {
    var token = event.authorizationToken;
    switch (token) {
        case 'allow':
            callback(null, generatePolicy('user', 'Allow', event.methodArn));
            break;
        case 'deny':
            callback(null, generatePolicy('user', 'Deny', event.methodArn));
            break;
        case 'unauthorized':
            callback("Unauthorized");   // Return a 401 Unauthorized response
            break;
        default:
            callback("Error: Invalid token"); // Return a 500 Invalid token response
    }
};

// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};
    
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; 
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; 
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}
```

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

```
# A simple token-based authorizer example to demonstrate how to use an authorization token
# to allow or deny a request. In this example, the caller named 'user' is allowed to invoke
# a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke
# the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty
# string, the authorizer function returns an HTTP 401 status code. For any other token value,
# the authorizer returns an HTTP 500 status code.
# Note that token values are case-sensitive.

import json


def lambda_handler(event, context):
    token = event['authorizationToken']
    if token == 'allow':
        print('authorized')
        response = generatePolicy('user', 'Allow', event['methodArn'])
    elif token == 'deny':
        print('unauthorized')
        response = generatePolicy('user', 'Deny', event['methodArn'])
    elif token == 'unauthorized':
        print('unauthorized')
        raise Exception('Unauthorized')  # Return a 401 Unauthorized response
        return 'unauthorized'
    try:
        return json.loads(response)
    except BaseException:
        print('unauthorized')
        return 'unauthorized'  # Return a 500 error


def generatePolicy(principalId, effect, resource):
    authResponse = {}
    authResponse['principalId'] = principalId
    if (effect and resource):
        policyDocument = {}
        policyDocument['Version'] = '2012-10-17'
        policyDocument['Statement'] = []
        statementOne = {}
        statementOne['Action'] = 'execute-api:Invoke'
        statementOne['Effect'] = effect
        statementOne['Resource'] = resource
        policyDocument['Statement'] = [statementOne]
        authResponse['policyDocument'] = policyDocument
    authResponse['context'] = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": True
    }
    authResponse_JSON = json.dumps(authResponse)
    return authResponse_JSON
```

------

在此示例中，当 API 接收方法请求时，API Gateway 将源令牌传递到 `event.authorizationToken` 属性中的此 Lambda 授权方函数。Lambda 授权方函数将读取令牌并按下所示做出行为：
+ 如果令牌值为 `allow`，该授权方函数将返回 `200 OK` HTTP 响应和 IAM 策略（类似于以下内容）并且方法请求成功：

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

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/"
      }
    ]
  }
  ```

------
+ 如果令牌值为 `deny`，该授权方函数将返回 `200 OK` HTTP 响应和 `Deny` IAM 策略（类似于以下内容）并且方法请求失败：

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

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Deny",
        "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/"
      }
    ]
  }
  ```

------
**注意**  
在测试环境之外，API Gateway 返回 `403 Forbidden` HTTP 响应并且方法请求将失败。
+ 如果令牌值为 `unauthorized` 或空字符串，该授权方函数将返回 `401 Unauthorized` HTTP 响应并且方法调用失败。
+ 如果令牌为任何其他内容，客户端将收到 `500 Invalid token` 响应并且方法调用失败。

除了返回 IAM 策略之外，Lambda 授权方函数还必须返回调用方的委托人标识符。它还可以选择返回一个 `context` 对象，其中包含可传入集成后端的其他信息。有关更多信息，请参阅 [来自 API Gateway Lambda 授权方的输出](api-gateway-lambda-authorizer-output.md)。

在生产代码中，您可能需要先对用户进行身份验证，然后才能授予授权。您可以通过调用身份验证提供程序，在 Lambda 函数中添加身份验证逻辑，如该提供程序的文档中的指示。

## 其他 Lambda 授权方函数示例
<a name="api-gateway-lambda-authorizer-lambda-function-create"></a>

以下列表显示了 Lambda 授权方函数的其他示例。您可以在创建 API 的相同账户或不同账户中创建 Lambda 函数。

对于前面的 Lambda 函数示例，您可以使用内置 [AWSLambdaBasicExecutionRole](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)，因为这些函数不会调用其他 AWS 服务。如果您的 Lambda 函数调用其他 AWS 服务，您需要为该 Lambda 函数分配 IAM 执行角色。要创建该角色，请按照 [AWS Lambda 执行角色](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)中的说明操作。

**其他 Lambda 授权方函数示例**
+  有关应用程序示例，请参阅 GitHub 中的 [Open Banking Brazil - Authorization Samples](https://github.com/aws-samples/openbanking-brazilian-auth-samples)。
+  有关更多示例 Lambda 函数，请参阅 GitHub 上的 [ aws-apigateway-lambda-authorizer-blueprints](https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints)。
+ 您可以创建 Lambda 授权方，该授权方使用 Amazon Cognito 用户池对用户进行身份验证，并使用 Verified Permissions 根据策略存储对调用方进行授权。有关更多信息，请参阅 [使用 Verified Permissions 根据身份的属性控制访问](apigateway-lambda-authorizer-verified-permissions.md)。
+ Lambda 控制台提供一个 Python 蓝图，您可以通过选择**使用蓝图**并选择 **api-gateway-authorizer-python** 蓝图来使用该蓝图。

# 配置 API Gateway Lambda 授权方
<a name="configure-api-gateway-lambda-authorization"></a>

创建 Lambda 函数后，您可以将 Lambda 函数配置为您的 API 的授权方。然后，您可以将方法配置为调用 Lambda 授权方，以确定调用方是否可以调用该方法。您可以在创建 API 的相同账户或不同账户中创建 Lambda 函数。

您可以使用 API Gateway 控制台中的内置工具或使用 [Postman](https://www.postman.com/) 来测试 Lambda 授权方。有关如何使用 Postman 测试 Lambda 授权方函数的说明，请参阅[使用 API Gateway Lambda 授权方调用 API](call-api-with-api-gateway-lambda-authorization.md)。

## 配置 Lambda 授权方（控制台）
<a name="configure-api-gateway-lambda-authorization-with-console"></a>

 以下过程介绍如何在 API Gateway REST API 控制台中创建 Lambda 授权方。要详细了解不同类型的 Lambda 授权方，请参阅[选择 Lambda 授权方类型](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-choose)。

------
#### [ REQUEST authorizer ]

**配置 `REQUEST` Lambda 授权方**

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

1. 选择一个 API，然后选择**授权方**。

1. 选择**创建授权方**。

1. 对于**授权方名称**，输入授权方名称。

1. 对于**授权方类型**，选择 **Lambda**。

1. 对于 **Lambda 函数**，选择您在其中创建 Lambda 授权方函数的 AWS 区域，然后输入函数名称。

1. 将 **Lambda 调用角色**留空，以允许 API Gateway REST API 控制台设置基于资源的策略。此策略授予 API Gateway 调用 Lambda 授权方函数的权限。您还可以选择输入 IAM 角色的名称，以允许 API Gateway 调用 Lambda 授权方函数。有关角色示例，请参阅[创建一个可代入的 IAM 角色](integrating-api-with-aws-services-lambda.md#api-as-lambda-proxy-setup-iam-role-policies)。

1. 对于 **Lambda 事件负载**，选择**请求**。

1. 在**身份来源类型**中，选择一个参数类型。支持的参数类型为 `Header`、`Query string`、`Stage variable` 和 `Context`。要添加更多身份来源，请选择**添加参数**。

1. 要缓存授权方生成的授权策略，请将**授权缓存**保持开启状态。在启用策略缓存后，您可以修改 **TTL** 值。将 **TTL** 设置为零将禁用策略缓存。

   如果启用缓存，授权方必须返回适用于 API 中所有方法的策略。要强制执行特定于方法的策略，请使用上下文变量 `$context.path` 和 `$context.httpMethod`。

1. 选择**创建授权方**。

------
#### [ TOKEN authorizer ]

**配置 `TOKEN` Lambda 授权方**

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

1. 选择一个 API，然后选择**授权方**。

1. 选择**创建授权方**。

1. 对于**授权方名称**，输入授权方名称。

1. 对于**授权方类型**，选择 **Lambda**。

1. 对于 **Lambda 函数**，选择您在其中创建 Lambda 授权方函数的 AWS 区域，然后输入函数名称。

1. 将 **Lambda 调用角色**留空，以允许 API Gateway REST API 控制台设置基于资源的策略。此策略授予 API Gateway 调用 Lambda 授权方函数的权限。您还可以选择输入 IAM 角色的名称，以允许 API Gateway 调用 Lambda 授权方函数。有关角色示例，请参阅[创建一个可代入的 IAM 角色](integrating-api-with-aws-services-lambda.md#api-as-lambda-proxy-setup-iam-role-policies)。

1. 对于 **Lambda 事件负载**，选择**令牌**。

1. 对于**令牌来源**，输入包含授权令牌的标头名称。客户端必须包括此标头名称才能将授权令牌发送到 Lambda 授权方。

1. （可选）对于**令牌验证**，请输入正则表达式语句。API Gateway 将针对此表达式执行对输入令牌的初始验证并在成功验证后调用授权方。

1. 要缓存授权方生成的授权策略，请将**授权缓存**保持开启状态。在启用策略缓存后，**令牌来源**中指定的标头名称将成为缓存键。在启用策略缓存后，您可以修改 **TTL** 值。将 **TTL** 设置为零将禁用策略缓存。

   如果启用缓存，授权方必须返回适用于 API 中所有方法的策略。要强制执行特定于方法的策略，您可以关闭**授权缓存**。

1. 选择**创建授权方**。

------

创建 Lambda 授权方后，您可以对其进行测试。以下过程介绍如何测试 Lambda 授权方。

------
#### [ REQUEST authorizer ]

**测试 `REQUEST` Lambda 授权方**

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

1. 选择授权方的名称。

1. 在**测试授权方**下，输入身份来源的值。

   如果您使用的是 [`REQUEST` 授权方 Lambda 函数示例](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-request-lambda-function-create)，请执行以下操作：

   1. 选择**标头**并输入 **headerValue1**，然后选择**添加参数**。

   1. 在**身份来源类型**下，选择**查询字符串**并输入 **queryValue1**，然后选择**添加参数**。

   1. 在**身份来源类型**下，选择**阶段变量**并输入 **stageValue1**。

   您无法修改测试调用的上下文变量，但可以修改 Lambda 函数的 **API Gateway 授权方**测试事件模板。然后，您可以使用修改后的上下文变量来测试 Lambda 授权方函数。有关更多信息，请参阅《AWS Lambda 开发人员指南》**中的[在控制台中测试 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/testing-functions.html)。

1. 选择**测试授权方**。

------
#### [ TOKEN authorizer ]

**测试 `TOKEN` Lambda 授权方**

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

1. 选择授权方的名称。

1. 在**测试授权方**下，输入令牌的值。

   如果您使用的是 [`TOKEN` 授权方 Lambda 函数示例](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-token-lambda-function-create)，请执行以下操作：

   1. 对于 **authorizationToken**，请输入 **allow**。

1. 选择**测试授权方**。

    如果 Lambda 授权方成功拒绝了测试环境中的请求，测试将返回 `200 OK` HTTP 响应。但在测试环境之外，API Gateway 将返回 `403 Forbidden` HTTP 响应并且方法请求将失败。

------

## 配置 Lambda 授权方（AWS CLI）
<a name="configure-api-gateway-lambda-authorization-cli"></a>

以下 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) 命令演示了如何使用 AWS CLI 创建 Lambda 授权方。

------
#### [ REQUEST authorizer ]

以下 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) 命令创建 `REQUEST` 授权方，并使用 `Authorizer` 标头和 `accountId` 上下文变量作为身份来源：

```
aws apigateway create-authorizer \
    --rest-api-id 1234123412 \
    --name 'First_Request_Custom_Authorizer' \
    --type REQUEST \
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123412341234:function:customAuthFunction/invocations' \
    --identity-source 'method.request.header.Authorization,context.accountId' \
    --authorizer-result-ttl-in-seconds 300
```

------
#### [ TOKEN authorizer ]

以下 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) 命令创建 `TOKEN` 授权方并使用 `Authorization` 标头作为身份来源：

```
aws apigateway create-authorizer \
    --rest-api-id 1234123412 \
    --name 'First_Token_Custom_Authorizer' \
    --type TOKEN \
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123412341234:function:customAuthFunction/invocations' \
    --identity-source 'method.request.header.Authorization' \
    --authorizer-result-ttl-in-seconds 300
```

------

创建 Lambda 授权方后，您可以对其进行测试。以下 [test-invoke-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/test-invoke-authorizer.html) 命令测试 Lambda 授权方：

```
aws apigateway test-invoke-authorizer --rest-api-id 1234123412 \
   --authorizer-id efg1234 \
   --headers Authorization='Value'
```

## 配置方法以使用 Lambda 授权方（控制台）
<a name="configure-api-gateway-lambda-authorization-method-console"></a>

配置 Lambda 授权方后，必须将其附加到 API 方法。如果授权方使用授权缓存，请务必更新策略以控制其它方法的访问权限。

**配置 API 方法以使用 Lambda 授权方**

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

1. 选择 API。

1. 选择**资源**，然后选择一种新方法或选择现有方法。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**授权方**，从下拉菜单中选择您刚刚创建的 Lambda 授权方。

1.  （可选）如果您希望将授权令牌传递到后端，请选择 **HTTP 请求标头**。选择**添加标头**，然后添加授权标头的名称。在**名称**中，输入标头名称，该名称必须与您在为 API 创建 Lambda 授权方时指定的**令牌来源**名称相匹配。此步骤不适用于 `REQUEST` 授权方。

1. 选择**保存**。

1. 选择**部署 API**，将 API 部署到某个阶段。对于使用阶段变量的 `REQUEST` 授权方，您还必须在**阶段**页面中定义必需的阶段变量并指定其值。

## 配置方法以使用 Lambda 授权方（AWS CLI）
<a name="configure-api-gateway-lambda-authorization-method-cli"></a>

配置 Lambda 授权方后，必须将其附加到 API 方法。您可以创建新方法或使用补丁操作将授权方附加到现有方法。如果授权方使用授权缓存，请务必更新策略以控制其它方法的访问权限。

以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建使用 Lambda 授权方的新方法：

```
aws apigateway put-method --rest-api-id 1234123412 \
  --resource-id a1b2c3 \
  --http-method PUT \
  --authorization-type CUSTOM \
  --authorizer-id efg1234
```

以下 [update-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-method.html) 命令更新现有方法以使用 Lambda 授权方：

```
aws apigateway update-method \
    --rest-api-id 1234123412 \
    --resource-id a1b2c3 \
    --http-method PUT \
    --patch-operations op="replace",path="/authorizationType",value="CUSTOM" op="replace",path="/authorizerId",value="efg1234"
```

# 向 API Gateway Lambda 授权方的输入
<a name="api-gateway-lambda-authorizer-input"></a>

以下部分介绍从 API Gateway 到 Lambda 授权方的输入的格式。

## `TOKEN` 输入格式
<a name="w2aac15b9c23c25c19b5"></a>

 对于 `TOKEN` 类型的 Lambda 授权方（以前称为自定义授权方），您必须在为 API 配置授权方时指定自定义标头作为**令牌源**。API 客户端必须在传入请求中传递该标头中必需的授权令牌。在收到传入方法请求后，API Gateway 将从自定义标头中提取此令牌。随后，它将此令牌作为 Lambda 函数的 `authorizationToken` 对象的 `event` 属性传递，并将方法 ARN 作为 `methodArn` 属性传递：

```
{
    "type":"TOKEN",
    "authorizationToken":"{caller-supplied-token}",
    "methodArn":"arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
```

 在此示例中，`type` 属性指定授权方类型，后者是 `TOKEN` 授权方。`{caller-supplied-token}` 源自客户端请求中的授权标头，可以是任何字符串值。`methodArn` 是传入方法请求的 ARN，由 API Gateway 根据 Lambda 授权方配置填充。

## `REQUEST` 输入格式
<a name="w2aac15b9c23c25c19b7"></a>

对于 `REQUEST` 类型的 Lambda 授权方，API Gateway 会将请求参数作为 `event` 对象的一部分传递到授权方 Lambda 函数。请求参数包括标头、路径参数、查询字符串参数、阶段变量以及一些请求上下文变量。API 调用方可以设置路径参数、标头和查询字符串参数。API 开发人员必须在 API 部署期间设置阶段变量，并且 API Gateway 将在运行时提供请求上下文。

**注意**  
路径参数可作为请求参数传递到 Lambda 授权方函数，但它们不能作身份来源。

 以下示例显示针对带代理集成的 API 方法 (`REQUEST`) 的 `GET /request` 授权方的输入：

```
{
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "resource": "/request",
  "path": "/request",
  "httpMethod": "GET",
  "headers": {
    "X-AMZ-Date": "20170718T062915Z",
    "Accept": "*/*",
    "HeaderAuth1": "headerValue1",
    "CloudFront-Viewer-Country": "US",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Is-Mobile-Viewer": "false",
    "User-Agent": "..."
  },
  "queryStringParameters": {
    "QueryString1": "queryValue1"
  },
  "pathParameters": {},
  "stageVariables": {
    "StageVar1": "stageValue1"
  },
  "requestContext": {
    "path": "/request",
    "accountId": "123456789012",
    "resourceId": "05c7jb",
    "stage": "test",
    "requestId": "...",
    "identity": {
      "apiKey": "...",
      "sourceIp": "...",
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "resourcePath": "/request",
    "httpMethod": "GET",
    "apiId": "abcdef123"
  }
}
```

 `requestContext` 是键值对的映射，与 [\$1context](api-gateway-mapping-template-reference.md#context-variable-reference) 变量相对应。其结果与 API 相关。

 API Gateway 可能会向映射中添加新键。有关 Lambda 代理集成中的 Lambda 函数输入的更多信息，请参阅 [用于代理集成的 Lambda 函数的输入格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format)。

# 来自 API Gateway Lambda 授权方的输出
<a name="api-gateway-lambda-authorizer-output"></a>

Lambda 授权方函数的输出是类似于目录的对象，其中必须包含委托人标识符 (`principalId`) 以及包含策略语句列表的策略文档 (`policyDocument`)。输出还可以包含一个含键值对的 `context` 映射。如果 API 利用使用计划（[https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apiKeySource](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apiKeySource) 设置为 `AUTHORIZER`），则 Lambda 授权方函数必须返回使用计划的 API 密钥之一作为 `usageIdentifierKey` 属性值。

下面显示了一个此类输出的示例。

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

****  

```
{
  "principalId": "yyyyyyyy", 
  "policyDocument": {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
      }
    ]
  },
  "context": {
    "stringKey": "value",
    "numberKey": "1",
    "booleanKey": "true"
  },
  "usageIdentifierKey": "{api-key}"
}
```

------

 在此示例中，策略语句指定是允许还是拒绝 (`Effect`) API Gateway 执行服务调用 (`Action`) 指定的 API 方法 (`Resource`)。可能需要根据授权方来控制对多个资源的访问权限。您可以使用通配符 (`*`) 指定资源类型（方法）。有关针对 API 调用设置有效策略的信息，请参阅[在 API Gateway 中执行 API 的 IAM 策略的语句参考](api-gateway-control-access-using-iam-policies-to-invoke-api.md#api-gateway-calling-api-permissions)。

对于已启用授权的方法 ARN，例如 `arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]`，最大长度为 1600 字节。路径参数值（其大小在运行时确定）可能导致 ARN 长度超过限制。出现这种情况是时，API 客户端将收到 `414 Request URI too long` 响应。

此外，如授权方的策略声明中所示，资源 ARN 当前长度限制为 512 个字符。因此，您不能在请求 URI 中将 URI 与具有很大长度的 JWT 令牌一起使用。而是可以安全地在请求标头中传递 JWT 令牌。

 您可以使用 `$context.authorizer.principalId` 变量访问映射模板中的 `principalId` 值。如果您想要将该值传递到后端，这会非常有用。有关更多信息，请参阅 [数据转换的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)。

 您可以通过分别调用 `$context.authorizer.stringKey`、`$context.authorizer.numberKey` 或 `$context.authorizer.booleanKey` 来访问映射模板中 `context` 映射的 `stringKey`、`numberKey` 或 `booleanKey` 值（如 `"value"`、`"1"` 或 `"true"`）。返回的值都是字符串化的。请注意，您不能在 `context` 映射中将 JSON 对象或数组设置为任何键的有效值。

 您可以使用 `context` 映射将缓存的凭证从授权方返回到后端（使用集成请求映射模板）。这使后端能够提供改善的用户体验，方式是使用缓存的凭证来减少为每个请求访问私有密钥并打开授权令牌的需要。

 对于 Lambda 代理集成，API Gateway 将 `context` 对象作为 `event` 输入的一部分从 Lambda 授权方直接传递到后端 Lambda 函数。您可以通过调用 `context`，在 Lambda 函数中检索 `$event.requestContext.authorizer.key` 键值对。

`{api-key}` 表示 API 阶段的使用计划中的 API 键。有关更多信息，请参阅 [API Gateway 中针对 REST API 的使用计划和 API 密钥](api-gateway-api-usage-plans.md)。

 下面显示了来自示例 Lambda 授权方的示例输出。此示例输出包含一个策略语句，用于阻止 (`Deny`) 在 `dev` 阶段调用AWS账户 (`123456789012`) API (`ymy8tbxw7b`) 的 `GET` 方法。

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

****  

```
{
  "principalId": "user",
  "policyDocument": {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Deny",
        "Resource": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/dev/GET/"
      }
    ]
  }
}
```

------

# 使用 API Gateway Lambda 授权方调用 API
<a name="call-api-with-api-gateway-lambda-authorization"></a>

 配置 Lambda 授权方（以前称为自定义授权方）并部署 API 后，您应在启用 Lambda 授权方的情况下测试 API。为此，您需要一个 REST 客户端（如 cURL 或 [Postman](https://www.postman.com/)）。对于以下示例，我们使用 Postman。

**注意**  
 调用已启用授权方的方法时，如果 `TOKEN` 授权方所需的令牌未设置、为 null 或由指定的**令牌验证表达式**认定为无效，则 API Gateway 不会将该调用记录到 CloudWatch 中。同样，如果 `REQUEST` 授权方所需的任何身份来源未设置、为 null 或为空，则 API Gateway 不会将该调用记录到 CloudWatch 中。

 在以下示例中，我们将说明如何在 Lambda `TOKEN` 授权方的情况下使用 Postman 调用或测试 API。如果您显式指定必需的路径、标头或查询字符串参数，则可应用此方法以使用 Lambda `REQUEST` 授权方调用 API。

**使用自定义 `TOKEN` 授权方调用 API**

1.  打开 **Postman**，选择 **GET** 方法，并将 API 的**调用 URL** 粘贴到相邻的 URL 字段中。

    添加 Lambda 授权令牌标头，并将值设置为 `allow`。选择**发送**。  
![\[使用 Lambda 授权允许令牌调用 API\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/custom-auth-call-api-with-allow-token.png)

    响应显示，API Gateway Lambda 授权方返回了 **200 OK** 响应，并成功授权调用访问与此方法集成的 HTTP 端点 (http://httpbin.org/get)。

1.  仍然是在 Postman 中，将 Lambda 授权令牌标头值更改为 `deny`。选择**发送**。  
![\[使用 Lambda 授权拒绝令牌调用 API\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/custom-auth-call-api-with-deny-token.png)

   响应显示，API Gateway Lambda 授权方返回了 **403 禁止访问**响应，而未授权调用访问 HTTP 端点。

1.  在 Postman 中，将 Lambda 授权令牌标头值更改为 `unauthorized`，并选择**发送**。  
![\[使用 Lambda 授权未授权令牌调用 API\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/custom-auth-call-api-with-unauthorized-token.png)

    响应显示，API Gateway 返回了 **401 未授权**响应，而未授权调用访问 HTTP 端点。

1.  现在，将 Lambda 授权令牌标头值更改为 `fail`。选择**发送**。  
![\[使用 Lambda 授权失败令牌调用 API\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/custom-auth-call-api-with-fail-token.png)

    响应显示，API Gateway 返回了 **500 内部服务器错误**响应，而未授权调用访问 HTTP 端点。

# 配置跨账户 API Gateway Lambda 授权方
<a name="apigateway-lambda-authorizer-cross-account-lambda-authorizer"></a>

您现在还可以使用其他 AWS Lambda 账户中的 AWS 函数作为 API 授权方函数。每个账户都可以位于 Amazon API Gateway 可用的任何区域中。Lambda 授权方函数可使用持有者令牌身份验证策略，如 OAuth 或 SAML。这样便可轻松地跨多个 API Gateway API 集中管理和共享重要的 Lambda 授权方函数。

在本节中，我们将介绍如何使用 Amazon API Gateway 控制台配置跨账户 Lambda 授权方函数。

这些说明假设您已经在一个AWS账户中有 API Gateway API，在另一个账户中有 Lambda 授权方函数。

## 使用 API Gateway 控制台配置跨账户 Lambda 授权方
<a name="apigateway-cross-account-lambda-auth-configure-cross-account-authorizer"></a>

在您拥有 API 的账户中登录 Amazon API Gateway 控制台，然后执行以下操作：

1. 选择您的 API，然后在主导航窗格中选择**授权方**。

1. 选择**创建授权方**。

1. 对于**授权方名称**，输入授权方名称。

1. 对于**授权方类型**，选择 **Lambda**。

1. 对于 **Lambda 函数**，输入您第二个账户中的 Lambda 授权方函数的完整 ARN。
**注意**  
在 Lambda 控制台中，您可以在控制台窗口的右上角找到函数的 ARN。

1. 此时将显示警告并带有 `aws lambda add-permission` 命令字符串。此策略授予 API Gateway 调用授权方 Lambda 函数的权限。复制命令并保存，以供稍后使用。您可在创建授权方后运行该命令。

1. 对于 **Lambda 事件有效载荷**，请选择**令牌**（对于 `TOKEN` 授权方）或**请求**（对于 `REQUEST` 授权方）。

1. 根据上一步的选择，执行下列操作之一：

   1.  对于**令牌**选项，执行下列操作：
      + 对于**令牌来源**，输入包含授权令牌的标头名称。API 客户端必须包括此标头名称才能将授权令牌发送到 Lambda 授权方。
      + 或者，对于**令牌验证**，输入正则表达式语句。API Gateway 将针对此表达式执行对输入令牌的初始验证并在成功验证后调用授权方。这有助于减少对您 API 的调用。
      + 要缓存授权方生成的授权策略，请将**授权缓存**保持开启状态。在启用策略缓存后，您可选择修改 **TTL** 值。将 **TTL** 设置为零将禁用策略缓存。在启用策略缓存后，**令牌来源**中指定的标头名称将成为缓存键。如果在请求中将多个值传递到此标头，则所有值都将成为缓存键，并保留顺序。
**注意**  
默认 **TTL** 值为 300 秒。最大值为 3600 秒；目前不能提高此限制。

   1. 对于**请求**选项，执行以下操作：
      + 在**身份源类型**中，选择一个参数类型。支持的参数类型为 `Header`、`Query string`、`Stage variable` 和 `Context`。要添加更多身份来源，请选择**添加参数**。
      + 要缓存授权方生成的授权策略，请将**授权缓存**保持开启状态。在启用策略缓存后，您可选择修改 **TTL** 值。将 **TTL** 设置为零将禁用策略缓存。

        API Gateway 将使用指定的身份来源作为请求授权方缓存键。在启用缓存后，API Gateway 将仅在成功确认所有指定的身份来源在运行时存在后才调用授权方的 Lambda 函数。如果指定的身份来源缺失、为 null 或为空，则 API Gateway 将返回 `401 Unauthorized` 响应，而不调用授权方 Lambda 函数。

        如果定义了多个身份来源，则它们都将用于派生授权方的缓存键。更改缓存键的任意部分将导致授权方丢弃缓存的策略文档并生成新的文档。如果在请求中传递了具有多个值的标头，则所有值都将成为缓存键的一部分，并保留顺序。
      + 在关闭缓存后，无需指定身份来源。
**注意**  
 要启用缓存，授权方必须返回适用于 API 中所有方法的策略。要强制执行特定于方法的策略，您可以关闭**授权缓存**。

1. 选择**创建授权方**。

1. 将您在上一步中复制的 `aws lambda add-permission` 命令字符串粘贴到为第二个账户配置的 AWS CLI 窗口中。使用您的授权方 ID 替换 `AUTHORIZER_ID`。这将向您的第一个账户授予对第二个账户的 Lambda 授权方函数的访问权限。

# 使用 Verified Permissions 根据身份的属性控制访问
<a name="apigateway-lambda-authorizer-verified-permissions"></a>

使用 Amazon Verified Permissions 控制对 API Gateway API 的访问。在将 API Gateway 与 Verified Permissions 结合使用时，Verified Permissions 会创建一个 Lambda 授权方，该授权者使用精细的授权决策来控制对 API 的访问。Verified Permissions 使用 Cedar 策略语言根据策略存储架构和策略来向调用方授权，以便为应用程序用户定义精细权限。有关更多信息，请参阅《Amazon Verified Permissions 用户指南》**中的 [Create a policy store with a connected API and identity provider](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/getting-started-api-policy-store.html)。

Verified Permissions 支持将 Amazon Cognito 用户池或 OpenID Connect（OIDC）身份提供商作为身份源。Verified Permissions 假设主体之前已被识别并经过身份验证。仅区域和边缘优化的 REST API 支持 Verified Permissions。

## 使用 Verified Permissions 创建 Lambda 授权方
<a name="apigateway-lambda-authorizer-verified-permissions-attach"></a>

Verified Permissions 会创建 Lambda 授权方以确定是否允许主体对 API 执行操作。您创建 Verified Permissions 用来执行其授权任务的 Cedar 策略。

以下是一个示例 Cedar 策略，该策略允许访问以调用基于 Amazon Cognito 用户池（即 API 的 `GET /users` 资源上的 `developer` 组的 `us-east-1_ABC1234`）的 API。Verified Permissions 通过解析调用方身份的持有者令牌来确定组成员资格。

```
permit(
  principal in MyAPI::UserGroup::"us-east-1_ABC1234|developer",
  action in [ MyAPI::Action::"get /users" ],
  resource
  );
```

（可选）Verified Permissions 可以将授权方附加到 API 的方法。在 API 的生产阶段，建议您禁止 Verified Permissions 为您附加授权方。

以下列表说明如何将 Verified Permissions 配置为附加或不附加到 API 方法的方法请求。

**为您附加授权方（AWS 管理控制台）**  
在 Verified Permissions 控制台中选择**创建策略存储**时，在**部署应用程序集成**页面上，选择**立即**。

**不要为您附加授权方（AWS 管理控制台）**  
在 Verified Permissions 控制台中选择**创建策略存储**时，在**部署应用程序集成**页面上，选择**稍后**。  
Verified Permissions 仍会为您创建 Lambda 授权方。Lambda 授权方以 `AVPAuthorizerLambda-` 开头。有关如何在方法上附加授权方的更多说明，请参阅[配置方法以使用 Lambda 授权方（控制台）](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-method-console)。

**为您附加授权方（CloudFormation）**  
在 Verified Permissions 生成的 CloudFormation 模板中，在 `Conditions` 部分中，将 `"Ref": "shouldAttachAuthorizer"` 设置为 `true`。

**不要为您附加授权方（CloudFormation）**  
在 Verified Permissions 生成的 CloudFormation 模板中，在 `Conditions` 部分中，将 `"Ref": "shouldAttachAuthorizer"` 设置为 `false`。  
Verified Permissions 仍会为您创建 Lambda 授权方。Lambda 授权方以 `AVPAuthorizerLambda-` 开头。有关如何在方法上附加授权方的更多说明，请参阅[配置方法以使用 Lambda 授权方（AWS CLI）](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-method-cli)。

## 使用 Verified Permissions 调用 Lambda 授权方
<a name="apigateway-lambda-authorizer-verified-permissions-call"></a>

您可以通过在 `Authorization` 标头中提供身份或访问令牌来调用您的 Lambda 授权方。有关更多信息，请参阅 [使用 API Gateway Lambda 授权方调用 API](call-api-with-api-gateway-lambda-authorization.md)。

API Gateway 会将 Lambda 授权方返回的策略缓存 120 秒。您可以在 API Gateway 控制台中或使用 AWS CLI 修改 TTL。

# 使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问
<a name="apigateway-integrate-with-cognito"></a>

作为使用 [IAM 角色和策略](permissions.md)或 [Lambda 授权方](apigateway-use-lambda-authorizer.md)（以前称为自定义授权方）的替代方案，您可以使用 [Amazon Cognito 用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html)来控制谁可以在 Amazon API Gateway 中访问您的 API。

要将 Amazon Cognito 用户池与您的 API 一起使用，您必须先创建 `COGNITO_USER_POOLS` 类型的授权方，然后配置 API 方法以使用该授权方。部署 API 之后，客户端必须先将用户注册到用户池，获取用户的[身份令牌或访问令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)，然后使用令牌之一调用 API 方法，这通常设置为请求的 `Authorization` 标头。只有提供了所需的令牌并且提供的令牌有效时，API 调用才会成功，否则，客户端未获得授权来执行调用，因为客户端没有可用于授权的凭证。

使用身份令牌，基于已登录用户的身份声明来授权 API 调用。使用访问令牌，基于指定访问受保护资源的自定义范围授权 API 调用。有关更多信息，请参阅[将令牌与用户池结合使用](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)和[资源服务器和自定义范围](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html)。

要为 API 创建和配置 Amazon Cognito 用户池，请执行以下任务：
+ 使用 Amazon Cognito 控制台、CLI/开发工具包或 API 创建用户池，或者使用由其他AWS账户拥有的用户池。
+ 使用 API Gateway 控制台、CLI/开发工具包或 API 创建具有选定用户池的 API Gateway Authorizer。
+ 使用 API Gateway 控制台、CLI/开发工具包或 API，在所选 API 方法上启用授权方。

 要在启用了用户池时调用任意 API 方法，您的客户端执行以下任务：
+  使用 Amazon Cognito CLI/SDK 或 API 将用户注册到所选用户池，并获取身份令牌或访问令牌。要了解有关使用 SDK 的更多信息，请参阅 [Code examples for Amazon Cognito using AWS SDKs](https://docs.aws.amazon.com/cognito/latest/developerguide/service_code_examples.html)。
+  使用客户端特定的框架调用已部署的 API Gateway API 并在 `Authorization` 标头中提供合适的令牌。

作为 API 开发人员，您必须向客户端开发人员提供用户池 ID、客户端 ID，并可能需要提供作为用户池的一部分定义的关联客户端密钥。

**注意**  
要允许用户使用 Amazon Cognito 凭证登录，同时还获取用于 IAM 角色权限的临时凭证，请使用 [Amazon Cognito 联合身份](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)。对于每个 API 资源端点 HTTP 方法，将授权类型、类别 `Method Execution` 设置为 `AWS_IAM`。

在此部分中，我们介绍如何创建用户池、如何将 API Gateway API 与用户池集成，以及如何调用与用户池集成的 API。

**Topics**
+ [为 REST API 创建 Amazon Cognito 授权用户池](apigateway-create-cognito-user-pool.md)
+ [将 REST API 与 Amazon Cognito 用户池集成](apigateway-enable-cognito-user-pool.md)
+ [调用与 Amazon Cognito 用户池集成的 REST API](apigateway-invoke-api-integrated-with-cognito-user-pool.md)
+ [使用 API Gateway 控制台为 REST API 配置跨账户 Amazon Cognito 授权方](apigateway-cross-account-cognito-authorizer.md)
+ [使用 CloudFormation 为 REST API 创建 Amazon Cognito 授权方](apigateway-cognito-authorizer-cfn.md)

# 为 REST API 创建 Amazon Cognito 授权用户池
<a name="apigateway-create-cognito-user-pool"></a>

将 API 与用户池集成之前，您必须在 Amazon Cognito 中创建用户池。您的用户群体配置必须遵守全部 [Amazon Cognito 的资源配额](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html)。所有用户定义的 Amazon Cognito 变量（如组、用户和角色）应仅使用字母数字字符。有关创建用户群体的说明，请参阅 [Amazon Cognito 开发人员指南](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html)中的*教程：创建用户池*。

记下用户池 ID、客户端 ID 和任意客户端密钥。客户端必须将这些信息提供给 Amazon Cognito，供用户注册到用户池、登录用户池，并获取要包含在请求中的身份令牌或访问令牌，以便调用配置了用户池的 API 方法。此外，在您将用户池配置为 API Gateway 中的授权方时，您还必须指定用户池名称，如下所述。

如果您使用访问令牌授权 API 方法调用，请确保使用用户池配置应用程序集成，以在指定资源服务器上设置您需要的自定义范围。有关将令牌与 Amazon Cognito 用户池结合使用的更多信息，请参阅[将令牌与用户池结合使用](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)。有关资源服务器的更多信息，请参阅[为您的用户池定义资源服务器](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html)。

记录配置的资源服务器标识符和自定义范围名称。您需要这些内容来构建 **OAuth Scopes (OAuth 范围)** 的访问范围完整名称，它由 `COGNITO_USER_POOLS` 授权方使用。

![\[Amazon Cognito 用户池资源服务器和范围\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/cognito-user-pool-custom-scopes-new-console.png)


# 将 REST API 与 Amazon Cognito 用户池集成
<a name="apigateway-enable-cognito-user-pool"></a>

创建 Amazon Cognito 用户池后，您必须在 API Gateway 中创建一个使用该用户池的 `COGNITO_USER_POOLS` 授权方。以下过程介绍如何使用 API Gateway 控制台执行此操作。

**注意**  
您可以使用 [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateAuthorizer.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateAuthorizer.html) 操作来创建使用多个用户池的 `COGNITO_USER_POOLS` 授权方。一个 `COGNITO_USER_POOLS` 授权方最多可以使用 1000 个用户池。不能提高此限制。

**重要**  
在执行以下任意步骤之后，您都需要部署或重新部署 API 以便传播更改。有关部署 API 的更多信息，请参阅[在 API Gateway 中部署 REST API。](how-to-deploy-api.md)。

**使用 API Gateway 控制台创建 `COGNITO_USER_POOLS` 授权方**

1. 在 API Gateway 中创建新的 API 或选择现有 API。

1. 在主导航窗格中，选择**授权方**。

1. 选择**创建授权方**。

1. 要配置新的授权方来使用用户池，请执行以下操作：

   1.  在**授权方名称**中，输入名称。

   1. 对于**授权方类型**，请选择 **Cognito**。

   1. 对于 **Cognito 用户群体**，请选择您创建 Amazon Cognito 的 AWS 区域并选择可用的用户群体。

      您可以使用阶段变量来定义用户池。对用户池使用以下格式：`arn:aws:cognito-idp:us-east-2:111122223333:userpool/${stageVariables.MyUserPool}`。

   1.  对于**令牌来源**，输入 **Authorization** 作为标头名称，以在用户成功登录时传递 Amazon Cognito 所返回的身份令牌或访问令牌。

   1. （可选）在**令牌验证**字段中输入一个正则表达式，以在使用 Amazon Cognito 对请求进行授权之前，验证身份令牌的 `aud`（受众）字段。请注意，在使用访问令牌时，由于访问令牌不包含 `aud` 字段，此验证将拒绝请求。

   1. 选择**创建授权方**。

1. 创建 `COGNITO_USER_POOLS` 授权方之后，您可以通过提供从用户池预置的身份验证令牌来对其进行测试调用。您不能使用访问令牌来对授权方进行测试调用。

   您可以通过调用 [Amazon Cognito 身份开发工具包](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html)来获取此身份令牌以执行用户登录。您也可以使用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) 操作。如果您未配置任何**授权范围**，API Gateway 会将提供的令牌视为身份令牌。

上述过程创建使用新创建的 Amazon Cognito 用户池的 `COGNITO_USER_POOLS` 授权方。根据在 API 方法上启用授权方的方法，您可以使用从集成用户池预置的身份令牌或访问令牌。

**在方法上配置 `COGNITO_USER_POOLS` 授权方**

1. 选择**资源**。选择新方法或选择现有方法。如有必要，请创建资源。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**授权方**，从下拉菜单中选择您刚刚创建的 **Amazon Cognito 用户群体授权方**。

1.  要使用身份令牌，请执行以下操作：

   1. 将**授权范围**保留为空。

   1. 如果需要，在**集成请求**中，在正文映射模板中添加 `$context.authorizer.claims['property-name']` 或 `$context.authorizer.claims.property-name` 表达式，从而将指定的身份声明属性从用户群体传递到后端。对于简单的属性名称，例如 `sub` 或 `custom-sub`，两种表示法相同。对于复杂的属性名称，例如 `custom:role`，不能使用点表示法。例如，以下映射表达式会将声明的 `sub` 和 `email` 的[标准字段](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)传递到后端：

      ```
      {
      	"context" : {
      		"sub" : "$context.authorizer.claims.sub",
      		"email" : "$context.authorizer.claims.email"
      	}
      }
      ```

      如果您在配置用户池时声明了自定义声明字段，那么您可以用同样的方式来访问自定义字段。以下示例获取的是声明的自定义 `role` 字段：

      ```
      {
      	"context" : {
      		"role" : "$context.authorizer.claims.role"
          }
      }
      ```

      如果自定义声明字段被声明为 `custom:role`，可以使用以下示例来获取声明的属性：

      ```
      {
      	"context" : {
      		"role" : "$context.authorizer.claims['custom:role']"
          }
      }
      ```

1.  要使用访问令牌，请执行以下操作：

   1. 对于**授权范围**，输入某个范围的一个或多个全名，该范围在创建 Amazon Cognito 用户池时已配置。例如，根据 [为 REST API 创建 Amazon Cognito 授权用户池](apigateway-create-cognito-user-pool.md) 中给出的示例，其中一个范围是 `https://my-petstore-api.example.com/cats.read`。

      在运行时，如果在此步骤的方法上指定的任何范围与在传入令牌中声明的范围匹配，则方法调用成功。否则，调用失败并出现 `401 Unauthorized` 响应。

   1.  选择**保存**。

1. 对您选择的其他方法重复这些步骤。

使用 `COGNITO_USER_POOLS` 授权方，如果未指定 **OAuth 范围**选项，则 API Gateway 将提供的令牌视为身份令牌，并根据来自用户池的身份之一验证所声明的身份。否则，API Gateway 将提供的令牌视为访问令牌，并根据在方法上声明的授权范围，验证在令牌中所声明的访问范围。

除了使用 API Gateway 控制台之外，您还可以指定 OpenAPI 定义文件并将 API 定义导入到 API Gateway，从而在方法上启用 Amazon Cognito 用户池。

**用 OpenAPI 定义文件导入 COGNITO\$1USER\$1POOLS 授权方**

1. 为您的 API 创建（或导出）一个 OpenAPI 定义文件。

1. 作为 OpenAPI 3.0 中的 `COGNITO_USER_POOLS` 部分或 Open API 2.0 中的 `MyUserPool` 部分，指定 `securitySchemes` 授权方 (`securityDefinitions`) JSON 定义，如下所示：

------
#### [ OpenAPI 3.0 ]

   ```
     "securitySchemes": {
       "MyUserPool": {
         "type": "apiKey",
         "name": "Authorization",
         "in": "header",
         "x-amazon-apigateway-authtype": "cognito_user_pools",
         "x-amazon-apigateway-authorizer": {
           "type": "cognito_user_pools",
           "providerARNs": [
             "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
           ]
         }
       }
   ```

------
#### [ OpenAPI 2.0 ]

   ```
     "securityDefinitions": {
       "MyUserPool": {
         "type": "apiKey",
         "name": "Authorization",
         "in": "header",
         "x-amazon-apigateway-authtype": "cognito_user_pools",
         "x-amazon-apigateway-authorizer": {
           "type": "cognito_user_pools",
           "providerARNs": [
             "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
           ]
         }
       }
   ```

------

1. 要将身份令牌用于方法授权，请将 `{ "MyUserPool": [] }` 添加到方法的 `security` 定义，如根资源上的以下 GET 方法所示。

   ```
     "paths": {
       "/": {
         "get": {
           "consumes": [
             "application/json"
           ],
           "produces": [
             "text/html"
           ],
           "responses": {
             "200": {
               "description": "200 response",
               "headers": {
                 "Content-Type": {
                   "type": "string"
                 }
               }
             }
           },
           "security": [
             {
               "MyUserPool": []
             }
           ],        
           "x-amazon-apigateway-integration": {
             "type": "mock",
             "responses": {
               "default": {
                 "statusCode": "200",
                 "responseParameters": {
                   "method.response.header.Content-Type": "'text/html'"
                 },
               }
             },
             "requestTemplates": {
               "application/json": "{\"statusCode\": 200}"
             },
             "passthroughBehavior": "when_no_match"
           }
         },
         ...
      }
   ```

1.  要为方法授权使用访问令牌，请将以上安全定义更改为 `{ "MyUserPool": [resource-server/scope, ...] }`：

   ```
     "paths": {
       "/": {
         "get": {
           "consumes": [
             "application/json"
           ],
           "produces": [
             "text/html"
           ],
           "responses": {
             "200": {
               "description": "200 response",
               "headers": {
                 "Content-Type": {
                   "type": "string"
                 }
               }
             }
           },
           "security": [
             {
               "MyUserPool": ["https://my-petstore-api.example.com/cats.read", "http://my.resource.com/file.read"]
             }
           ],        
           "x-amazon-apigateway-integration": {
             "type": "mock",
             "responses": {
               "default": {
                 "statusCode": "200",
                 "responseParameters": {
                   "method.response.header.Content-Type": "'text/html'"
                 },
               }
             },
             "requestTemplates": {
               "application/json": "{\"statusCode\": 200}"
             },
             "passthroughBehavior": "when_no_match"
           }
         },
         ...
      }
   ```

1. 如果需要，您可以使用合适的 OpenAPI 定义或扩展来设置其他 API 配置设置。有关更多信息，请参阅 [适用于 API Gateway 的 OpenAPI 扩展](api-gateway-swagger-extensions.md)。

# 调用与 Amazon Cognito 用户池集成的 REST API
<a name="apigateway-invoke-api-integrated-with-cognito-user-pool"></a>

要调用一个配置了用户池授权方的方法，客户端必须执行以下操作：
+ 让用户注册到用户池中。
+ 让用户登录用户池。
+ 从用户池获取已登录用户的[身份或访问令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)。
+ 将令牌添加到 `Authorization` 标头（或您创建授权方时指定的其他标头）中。

您可以使用 [AWS Amplify]() 来执行这些任务。有关更多信息，请参阅[将 Amazon Cognito 与 Web 和移动应用程序集成](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html)。
+ 对于 Android，请参阅 [Amplify for Android 入门](https://docs.amplify.aws/android/build-a-backend/auth/)。
+ 要使用 iOS，请参阅 [Amplify for iOS 入门](https://docs.amplify.aws/swift/build-a-backend/auth/)。
+ 要使用 JavaScript，请参阅 [Amplify for Javascript 入门](https://docs.amplify.aws/javascript/build-a-backend/auth/)。

# 使用 API Gateway 控制台为 REST API 配置跨账户 Amazon Cognito 授权方
<a name="apigateway-cross-account-cognito-authorizer"></a>

您现在还可以使用来自其他 AWS 账户的 Amazon Cognito 用户池作为 API 授权方。Amazon Cognito 用户池可使用持有者令牌身份验证策略（如 OAuth 或 SAML）。这样就可以轻松地跨多个 API Gateway API 集中管理和共享中央 Amazon Cognito 用户池授权方。

在本节中，我们将介绍如何使用 Amazon API Gateway 控制台配置跨账户 Amazon Cognito 用户池。

这些说明假定您已在一个 AWS 账户中拥有 API Gateway API，在另一个账户中有 Amazon Cognito 用户池。

## 为 REST API 创建跨账户 Amazon Cognito 授权方
<a name="apigateway-configure-cross-account-cognito-authorizer"></a>

在您拥有 API 的账户中登录 Amazon API Gateway 控制台，然后执行以下操作：

1. 在 API Gateway 中创建新的 API 或选择现有 API。

1. 在主导航窗格中，选择**授权方**。

1. 选择**创建授权方**。

1. 要配置新的授权方来使用用户池，请执行以下操作：

   1.  在**授权方名称**中，输入名称。

   1. 对于**授权方类型**，请选择 **Cognito**。

   1. 对于 **Cognito 用户群体**，输入您第二个账户中的用户群体的完整 ARN。
**注意**  
在 Amazon Cognito 控制台中，您可以在**常规设置**窗格的**池 ARN** 字段找到您的用户池的 ARN。

   1.  对于**令牌来源**，输入 **Authorization** 作为标头名称，以在用户成功登录时传递 Amazon Cognito 所返回的身份令牌或访问令牌。

   1. （可选）在**令牌验证**字段中输入一个正则表达式，以在使用 Amazon Cognito 对请求进行授权之前，验证身份令牌的 `aud`（受众）字段。请注意，在使用访问令牌时，由于访问令牌不包含 `aud` 字段，此验证将拒绝请求。

   1. 选择**创建授权方**。

# 使用 CloudFormation 为 REST API 创建 Amazon Cognito 授权方
<a name="apigateway-cognito-authorizer-cfn"></a>

可以使用 CloudFormation 创建 Amazon Cognito 用户群体和 Amazon Cognito 授权方。示例 CloudFormation 模板执行以下操作：
+ 创建 Amazon Cognito 用户群体。客户端必须先将用户登录到用户群体并获取[身份或访问令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)。如果您使用访问令牌授权 API 方法调用，请确保使用用户池配置应用程序集成，以在指定资源服务器上设置您需要的自定义范围。
+ 使用 `GET` 方法创建 API Gateway API。
+ 创建使用 `Authorization` 标头作为令牌来源的 Amazon Cognito 授权方。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: verified_phone_number
            Priority: 1
          - Name: verified_email
            Priority: 2
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
      EmailVerificationMessage: The verification code to your new account is {####}
      EmailVerificationSubject: Verify your new account
      SmsVerificationMessage: The verification code to your new account is {####}
      VerificationMessageTemplate:
        DefaultEmailOption: CONFIRM_WITH_CODE
        EmailMessage: The verification code to your new account is {####}
        EmailSubject: Verify your new account
        SmsMessage: The verification code to your new account is {####}
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
  CogAuthorizer:
    Type: AWS::ApiGateway::Authorizer
    Properties:
      Name: CognitoAuthorizer
      RestApiId:
        Ref: Api
      Type: COGNITO_USER_POOLS
      IdentitySource: method.request.header.Authorization
      ProviderARNs:
        - Fn::GetAtt:
            - UserPool
            - Arn
  Api:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: MyCogAuthApi
  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId:
        Ref: Api
    DependsOn:
      - CogAuthorizer
      - ApiGET
  ApiDeploymentStageprod:
    Type: AWS::ApiGateway::Stage
    Properties:
      RestApiId:
        Ref: Api
      DeploymentId:
        Ref: ApiDeployment
      StageName: prod
  ApiGET:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: GET
      ResourceId:
        Fn::GetAtt:
          - Api
          - RootResourceId
      RestApiId:
        Ref: Api
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId:
        Ref: CogAuthorizer
      Integration:
        IntegrationHttpMethod: GET
        Type: HTTP_PROXY
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Outputs:
  ApiEndpoint:
    Value:
      Fn::Join:
        - ""
        - - https://
          - Ref: Api
          - .execute-api.
          - Ref: AWS::Region
          - "."
          - Ref: AWS::URLSuffix
          - /
          - Ref: ApiDeploymentStageprod
          - /
```

# 针对 API Gateway 中的 REST API 的集成
<a name="how-to-integration-settings"></a>

 设置 API 方法之后，您必须将其与后端中的端点集成。后端端点也称为集成端点，它可以是 Lambda 函数、HTTP 网页或 AWS 服务操作。

使用 API 方法，API 集成有一个集成请求和一个集成响应。集成请求封装后端收到的 HTTP 请求。它可能与客户端提交的方法请求不同或相同。集成响应是封装了后端返回的输出的 HTTP 响应。

设置集成请求涉及以下内容：配置如何将客户端提交的方法请求传递到后端；配置如何将请求数据转换为集成请求数据（如有必要）；指定要调用的 Lambda 函数，指定将传入请求转发到哪个 HTTP 服务器，或者指定要调用的AWS服务操作。

设置集成响应（仅适用于非代理集成）涉及以下内容：配置如何传递后端返回的结果到具有指定状态代码的方法响应，配置如何转换指定的集成响应参数为预配置的方法响应参数，以及配置如何根据指定的正文映射模板将集成响应正文映射到方法响应正文。

集成请求由 API Gateway 的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 资源以编程方式封装，集成响应由 [https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源以编程方式封装。

要设置集成请求，您需要创建 [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 资源并用它来配置集成端点 URL。然后，您可以设置 IAM 权限以访问后端，并指定映射以在将传入请求数据传递到后端之前进行转换。要为非代理集成设置集成响应，您需要创建 [https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源并用它设置其目标方法响应。然后，您可以配置如何将后端输出映射到方法响应。

**Topics**
+ [在 API Gateway 中设置集成请求](api-gateway-integration-settings-integration-request.md)
+ [在 API Gateway 中设置集成响应](api-gateway-integration-settings-integration-response.md)
+ [针对 API Gateway 中的 REST API 的 Lambda 集成](set-up-lambda-integrations.md)
+ [针对 API Gateway 中的 REST API 的 HTTP 集成](setup-http-integrations.md)
+ [在 API Gateway 中流式传输代理集成的集成响应](response-transfer-mode.md)
+ [针对 API Gateway 中的 REST API 的私有集成](private-integration.md)
+ [针对 API Gateway 中的 REST API 的模拟集成](how-to-mock-integration.md)

# 在 API Gateway 中设置集成请求
<a name="api-gateway-integration-settings-integration-request"></a>

要设置集成请求，您可以执行以下必需任务和可选任务：

1.  选择确定如何将方法请求数据传递到后端的集成类型。

1.  对于非模拟集成，请指定 HTTP 方法和目标集成端点的 URI，但 `MOCK` 集成除外。

1.  对于与 Lambda 函数和其他AWS服务操作的集成，请设置具有所需权限的 IAM 角色，以便 API Gateway 代表您调用后端。

1.  对于非代理集成，设置必要的参数映射，将预定义方法请求参数映射到合适的集成请求参数。

1.  对于非代理集成，设置必要的正文映射，根据指定的映射模板来映射给定内容类型的传入方法请求正文。

1.  对于非代理集成，指定传入方法请求按原样传递到后端的条件。

1.  （可选）指定如何处理二进制负载的类型转换。

1.  （可选）声明缓存命名空间名称和缓存密钥参数以启用 API 缓存。

 执行这些任务涉及到创建 API Gateway 的[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)资源以及设置合适的属性值。您可以使用 API Gateway 控制台、AWS CLI 命令、AWS 开发工具包或 API Gateway REST API 来执行此操作。

**Topics**
+ [API 集成请求的基本任务](integration-request-basic-setup.md)
+ [选择 API Gateway API 集成类型](api-gateway-api-integration-types.md)
+ [设置具有代理资源的代理集成](api-gateway-set-up-simple-proxy.md)
+ [使用 API Gateway 控制台设置 API 集成请求](how-to-method-settings-console.md)

# API 集成请求的基本任务
<a name="integration-request-basic-setup"></a>

 集成请求是 API Gateway 提交到后端的 HTTP 请求，与客户端提交的请求数据一起传递，并在需要时转换数据。HTTP 方法（或动词）和集成请求的 URI 由后端（即，集成端点）决定。它们分别可以与方法请求的 HTTP 方法和 URI 相同或不同。

例如，当 Lambda 函数返回从 Amazon S3 提取的文件时，您可以直观地公开此操作，作为对客户端的 `GET` 方法请求，即使对应的集成请求需要使用 `POST` 请求来调用 Lambda 函数。对于 HTTP 端点，有可能方法请求和对应的集成请求均使用相同的 HTTP 动词。但这不是必需的。您可以集成以下方法请求：

```
GET /{var}?query=value
Host: api.domain.net
```

使用以下集成请求：

```
POST /
Host: service.domain.com
Content-Type: application/json
Content-Length: ...

{
   path: "{var}'s value",
   type: "value"
}
```

 作为 API 开发人员，您可以为方法请求使用任意满足需求的 HTTP 动词和 URI。但是，您必须遵守集成端点的要求。当方法请求数据不同于集成请求数据时，您可以通过提供从方法请求数据到集成请求数据的映射来协调差异。

在前面的示例中，映射将 `{var}` 方法请求的路径变量 (`query`) 和查询参数 (`GET`) 值转换为集成请求的负载属性 `path` 和 `type` 的值。其他可映射请求数据包含请求标头和正文。[API Gateway 中 REST API 的参数映射](rest-api-parameter-mapping.md) 中介绍了这些内容。

设置 HTTP 或 HTTP 代理集成请求时，您分配后端 HTTP 端点 URL 作为集成请求 URI 值。例如，在 PetStore API 中，用于获取一页宠物的方法请求具有以下集成请求 URI：

```
http://petstore-demo-endpoint.execute-api.com/petstore/pets
```

在设置 Lambda 或 Lambda 代理集成时，您分配 Amazon Resource Name (ARN) 用于调用 Lambda 函数作为集成请求 URI 值。此 ARN 具有以下格式：

```
arn:aws:apigateway:api-region:lambda:path//2015-03-31/functions/arn:aws:lambda:lambda-region:account-id:function:lambda-function-name/invocations
```

`arn:aws:apigateway:api-region:lambda:path/` 之后的部分，即 `/2015-03-31/functions/arn:aws:lambda:lambda-region:account-id:function:lambda-function-name/invocations`，是 Lambda [调用](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html)操作的 REST API URI 路径。如果您使用 API Gateway 控制台来设置 Lambda 集成，API Gateway 会在提示您从区域中选择 `lambda-function-name` 之后，创建 ARN 并将其分配给集成 URI。

使用其他AWS服务操作设置集成请求时，集成请求 URI 也是 ARN，类似于使用 Lambda `Invoke` 操作的集成。例如，对于具有 Amazon S3 的 [GetBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) 操作的集成，集成请求 URI 是以下格式的 ARN：

```
arn:aws:apigateway:api-region:s3:path/{bucket}
```

集成请求 URI 是用于指定操作的路径约定，其中 `{bucket}` 是存储桶名称的占位符。此外，AWS 服务操作可以按其名称引用。使用操作名称，Amazon S3 的 `GetBucket` 操作的集成请求 URI 成为以下内容：

```
arn:aws:apigateway:api-region:s3:action/GetBucket
```

使用基于操作的集成请求 URI，存储桶名称 (`{bucket}`) 必须在集成请求正文中指定 (`{ Bucket: "{bucket}" }`)，按照 `GetBucket` 操作的输入格式。

对于‭AWS‬集成，您还必须配置[凭证](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#credentials)以允许 API Gateway 调用集成操作。您可以为 API Gateway 创建新的 IAM 角色或选择现有此类角色以调用操作，然后使用其 ARN 指定角色。下面显示了此 ARN 的示例：

```
arn:aws:iam::account-id:role/iam-role-name
```

此 IAM 角色必须包含策略以允许执行操作。它还必须将 API Gateway 声明（在角色的信任关系中）作为可信实体以代入角色。此类权限可以在操作本身上授予。他们被称为基于资源的权限。对于 Lambda 集成，您可以调用 Lambda 的 [addPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html) 操作来设置基于资源的权限，然后在 API Gateway 集成请求中将 `credentials` 设置为 null。

我们讨论了基本集成设置。高级设置涉及到将方法请求数据映射到集成请求数据。有关更多信息，请参阅 [针对 API Gateway 中 REST API 的数据转换](rest-api-data-transformations.md)。

# 选择 API Gateway API 集成类型
<a name="api-gateway-api-integration-types"></a>



 您可以根据所使用的集成端点的类型以及希望如何与集成端点往返传输数据，来选择 API 集成类型。对于 Lambda 函数，您可以使用 Lambda 代理集成或 Lambda 自定义集成。对于 HTTP 端点，您可以使用 HTTP 代理集成，或者 HTTP 自定义集成。对于 AWS 服务操作，您只能使用非代理类型的 AWS 集成。API Gateway 还支持模拟集成，在这种情况下，API Gateway 用作集成端点来响应方法请求。

Lambda 自定义集成是‭AWS‬集成的特殊用例，其中集成端点对应于 Lambda 服务的[函数调用操作](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html)。

您可以采用编程方式，通过设置 [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 资源中的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#type](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#type) 属性来选择集成类型。对于 Lambda 代理集成，该值为 `AWS_PROXY`。对于 Lambda 自定义集成以及所有其他AWS集成，这是 `AWS`。对于 HTTP 代理集成和 HTTP 集成，该值分别为 `HTTP_PROXY` 和 `HTTP`。对于模拟集成，`type` 值为 `MOCK`。

Lambda 代理集成支持通过单个 Lambda 函数来简化集成设置。设置很简单，并且可以随后端演变，而无需停用现有设置。出于这些原因，强烈建议使用 Lambda 函数集成。

相比之下，Lambda 自定义集成允许将配置的映射模板用于各种具有类似输入和输出数据格式要求的集成端点。设置会更为复杂，建议用于更高级的应用程序场景。

同样，HTTP 代理集成具有简化的集成设置，可以随后端演变，而无需停用现有设置。HTTP 自定义集成的设置更为复杂，但允许将配置的映射模板重新用于其他集成端点。

下表汇总了支持的端点类型：
+ `AWS`：这种类型的集成使得 API 可以公开 AWS 服务操作。在 `AWS` 集成中，您必须同时配置集成请求和集成响应，并设置从方法请求到集成请求以及从集成响应到方法响应的必需数据映射。
+  `AWS_PROXY`：这种类型的集成让 API 方法可以通过灵活、多功能和简化的集成设置与 Lambda 函数调用操作集成。这种集成依赖于客户端与集成的 Lambda 函数之间的直接交互。

  借助于这类集成，也称为 Lambda 代理集成，您无需设置集成请求或集成响应。API Gateway 将来自客户端的传入请求作为输入传递给后端 Lambda 函数。集成 Lambda 函数采用[此格式的输入](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format)并解析来自所有可用源的输入，包括请求标头、URL 路径变量、查询字符串参数以及适用的正文。函数返回的结构遵守此[输出格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format)。

  这是通过 API Gateway 调用 Lambda 函数的首选集成类型，不适用于任何其他AWS服务操作，包括函数调用操作之外的 Lambda 操作。
+ `HTTP`：这种类型的集成允许 API 在后端中公开 HTTP 端点。借助于 `HTTP` 集成，也称为 HTTP 自定义集成，您必须同时配置集成请求和集成响应。您必须设置从方法请求到集成请求以及从集成响应到方法响应的必需映射。
+  `HTTP_PROXY`：HTTP 代理集成允许客户端使用单个 API 方法上的简化集成设置来访问后端 HTTP 端点。您无需设置集成请求或集成响应。API Gateway 将来自客户端的传入请求传递到 HTTP 端点，并将来自 HTTP 端点的传出响应传递到客户端。
+ `MOCK`：这种类型的集成允许 API Gateway 返回响应而不将请求进一步发送给后端。这对于 API 测试非常有用，因为它可用于测试集成设置而不会导致使用后端的收费，并可以实现协作开发 API。

  在协作开发中，团队可以通过使用 `MOCK` 集成，设置其他团队拥有的 API 组件的模拟，从而隔离其开发工作。它还可用于返回与 CORS 相关的标头以确保 API 方法允许 CORS 访问。事实上，API Gateway 控制台集成 `OPTIONS` 方法以通过模拟集成来支持 CORS。[网关响应](api-gateway-gatewayResponse-definition.md#customize-gateway-responses)是模拟集成的其他示例。

# 设置具有代理资源的代理集成
<a name="api-gateway-set-up-simple-proxy"></a>

要在 API Gateway API 中设置具有[代理资源](api-gateway-method-settings-method-request.md#api-gateway-proxy-resource)的代理集成，您需要执行以下任务：
+ 创建一个“贪婪”路径变量为 `{proxy+}` 的代理资源。
+ 在代理资源上设置 `ANY` 方法。
+ 使用 HTTP 或 Lambda 集成类型将资源和方法与后端相集成。

**注意**  
“贪婪”路径变量、`ANY` 方法和代理集成类型通常结合使用，但它们都是独立的功能。您可以在“贪婪”资源上配置特定 HTTP 方法，也可以将非代理集成类型应用于代理资源。

在通过 Lambda 代理集成或 HTTP 代理集成处理方法时，API Gateway 存在某些限制。有关详细信息，请参阅[Amazon API Gateway 重要说明](api-gateway-known-issues.md)。

**注意**  
 将代理集成与传递搭配使用时，如果未指定负载的内容类型，则 API Gateway 将返回默认的 `Content-Type:application/json` 标头。

使用以下 HTTP 代理集成或 Lambda 代理[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)将代理资源与后端集成时，该代理资源的功能最为强大。

## 具有代理资源的 HTTP 代理集成
<a name="api-gateway-proxy-integration-types"></a>

HTTP 代理集成，在 API Gateway REST API 中由 `HTTP_PROXY` 指定，用于将方法请求与后端 HTTP 终端节点集成。使用此集成类型，API Gateway 只需遵守特定[限制](api-gateway-known-issues.md)在前端和后端之间传递整个请求和响应。

**注意**  
HTTP 代理集成支持多值标头和查询字符串。

将 HTTP 代理集成用于代理资源时，您可以设置 API 来公开采用单个集成设置的 HTTP 后端的部分或整个终端节点层次结构。例如，假设将网站后端组织成多个脱离根节点 (`/site`) 的树节点的多个分支，如 `/site/a0/a1/.../aN`、`/site/b0/b1/.../bM` 等。如果将 `ANY` 的代理资源上的 `/api/{proxy+}` 方法与 URL 路径为 `/site/{proxy}` 的后端终端节点集成，则单个集成请求可以支持任何 HTTP 操作（GET、POST 等），在任何 `[a0, a1, ..., aN, b0, b1, ...bM, ...]` 上都如此。如果您将代理集成应用于特定的 HTTP 方法（如 `GET`），则生成的集成请求将与任何后端节点上的指定（即 `GET`）操作配合发挥作用。

## 具有代理资源的 Lambda 代理集成
<a name="lambda-proxy-integration-with-proxy-resource"></a>

Lambda 代理集成，在 API Gateway REST API 中由 `AWS_PROXY` 指定，用于将方法请求与后端中的 Lambda 函数集成。使用这种集成类型，API Gateway 会应用默认映射模板将整个请求发送到 Lambda 函数，并将 Lambda 函数的输出转换为 HTTP 响应。

同样，您可以将 Lambda 代理集成应用于 `/api/{proxy+}` 的代理资源以设置单个集成，从而让后端 Lambda 函数单独响应 `/api` 下任何 API 资源的更改。

# 使用 API Gateway 控制台设置 API 集成请求
<a name="how-to-method-settings-console"></a>

 API 方法设置定义该方法并描述其行为。要设置方法，您必须指定一个包含根 (“/”) 的资源以便在其中公开该方法，并指定 HTTP 方法（`GET`、`POST` 等）以及该方法如何与目标后端集成。方法请求和响应指定与调用应用程序的协定，其中规定 API 可以接收哪些参数以及响应是什么样子。

 以下过程介绍如何使用 API Gateway 控制台创建集成请求。

**Topics**
+ [设置 Lambda 集成](#how-to-method-settings-console-lambda)
+ [设置 HTTP 集成](#how-to-method-settings-console-http)
+ [设置 AWS 服务集成](#how-to-method-settings-console-aws)
+ [设置模拟集成](#how-to-method-settings-console-mock)

## 设置 Lambda 集成
<a name="how-to-method-settings-console-lambda"></a>

使用 Lambda 函数集成，来将您的 API 与 Lambda 函数集成。在 API 级别，如果您创建非代理集成，则这是 `AWS` 集成类型；如果您创建代理集成，则这是 `AWS_PROXY` 集成类型。

**设置 Lambda 集成**

1. 在**资源**窗格中，选择**创建方法**。

1. 对于**方法类型**，选择一种 HTTP 方法。

1. 对于**集成类型**，选择 **Lambda 函数**。

1. 要使用 Lambda 代理集成，请开启 **Lambda 代理集成**。要了解有关 Lambda 代理集成的更多信息，请参阅[了解 API Gateway Lambda 代理集成](set-up-lambda-proxy-integrations.md#api-gateway-create-api-as-simple-proxy)。

1. 对于 **Lambda 函数**，输入函数 Lambda 的名称。

    如果您在与您的 API 不同的区域中使用 Lambda 函数，请从下拉菜单中选择该区域并输入 Lambda 函数的名称。如果您使用的是跨账户 Lambda 函数，请输入函数 ARN。

1. 要使用默认超时值 29 秒，请保持**默认超时**处于开启状态。要设置自定义超时，请选择**默认超时**，然后输入一个介于 `50` 到 `29000` 毫秒之间的超时值。

1. （可选）您可以使用以下下拉菜单配置方法请求设置。选择**方法请求设置**并配置您的方法请求。有关更多信息，请参阅[在 API Gateway 控制台中编辑 API Gateway 方法请求](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)的步骤 3。

   您也可以在创建方法后配置方法请求设置。

1. 选择**创建方法**。

## 设置 HTTP 集成
<a name="how-to-method-settings-console-http"></a>

使用 HTTP 集成将您的 API 与 HTTP 端点集成。在 API 级别，这是 `HTTP` 集成类型。

**设置 HTTP 集成**

1. 在**资源**窗格中，选择**创建方法**。

1. 对于**方法类型**，选择一种 HTTP 方法。

1. 对于**集成类型**，选择 **HTTP**。

1. 要使用 HTTP 代理集成，请开启 **HTTP 代理集成**。要了解有关 HTTP 代理集成的更多信息，请参阅[在 API Gateway 中设置 HTTP 代理集成](setup-http-integrations.md#api-gateway-set-up-http-proxy-integration-on-proxy-resource)。

1. 对于 **HTTP 方法**，选择与 HTTP 后端中的方法最匹配的 HTTP 方法类型。

1. 对于**端点 URL**，输入您希望此方法使用的 HTTP 后端的 URL。

1. 对于**内容处理**，请选择内容处理行为。

1. 要使用默认超时值 29 秒，请保持**默认超时**处于开启状态。要设置自定义超时，请选择**默认超时**，然后输入一个介于 `50` 到 `29000` 毫秒之间的超时值。

1. （可选）您可以使用以下下拉菜单配置方法请求设置。选择**方法请求设置**并配置您的方法请求。有关更多信息，请参阅[在 API Gateway 控制台中编辑 API Gateway 方法请求](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)的步骤 3。

   您也可以在创建方法后配置方法请求设置。

1. 选择**创建方法**。

## 设置 AWS 服务集成
<a name="how-to-method-settings-console-aws"></a>

使用 AWS 服务集成将您的 API 直接与 AWS 服务集成。在 API 级别，这是 `AWS` 集成类型。

设置 API Gateway API 执行以下任一操作：
+ 新建 Lambda 函数。
+ 设置 Lambda 函数的资源权限。
+ 执行任何其它 Lambda 服务操作。

您必须选择 **AWS 服务**。

**设置 AWS 服务集成**

1. 在**资源**窗格中，选择**创建方法**。

1. 对于**方法类型**，选择一种 HTTP 方法。

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

1. 对于 **AWS 区域**，选择您希望此方法用于调用操作的 AWS 区域。

1. 对于 **AWS 服务**，选择您希望此方法调用的 AWS 服务。

1.  对于 **AWS 子域**，请输入 AWS 服务使用的子域。通常，您会将此项保留为空。某些 AWS 服务可以支持子域作为主机的一部分。有关可用性和详细信息 (如果有)，请参阅服务文档。

1. 对于 **HTTP 方法**，选择与操作对应的 HTTP 方法类型。对于 HTTP 方法类型，请参阅您为 **AWS 服务**选择的 AWS 服务的 API 参考文档。

1. 对于**操作类型**，选择**使用操作名称**以使用 API 操作，或选择**使用路径覆盖**以使用自定义资源路径。有关可用的操作和自定义资源路径，请参阅您为 **AWS 服务**选择的 AWS 服务的 API 参考文档。

1. 输入**操作名称**或**路径覆盖**。

1. 对于**执行角色**，输入该方法将用于调用操作的 IAM 角色的 ARN。

   要创建 IAM 角色，您可以调整[步骤 1：创建 AWS 服务代理执行角色](getting-started-aws-proxy.md#getting-started-aws-proxy-add-roles)中的说明。使用所需数量的操作和资源语句指定访问策略。有关更多信息，请参阅 [Amazon API Gateway 如何与 IAM 配合使用](security_iam_service-with-iam.md)。

   有关操作和资源语句语法，请参阅您为 **AWS 服务**选择的 AWS 服务的文档。

   有关 IAM 角色的信任关系，请指定以下内容，使 API Gateway 代表您的AWS账户采取行动：

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

****  

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

------

1. 要使用默认超时值 29 秒，请保持**默认超时**处于开启状态。要设置自定义超时，请选择**默认超时**，然后输入一个介于 `50` 到 `29000` 毫秒之间的超时值。

1. （可选）您可以使用以下下拉菜单配置方法请求设置。选择**方法请求设置**并配置您的方法请求。有关更多信息，请参阅[在 API Gateway 控制台中编辑 API Gateway 方法请求](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)的步骤 3。

   您也可以在创建方法后配置方法请求设置。

1. 选择**创建方法**。

## 设置模拟集成
<a name="how-to-method-settings-console-mock"></a>

 如果您希望 API Gateway 充当您的后端来返回静态响应，则使用模拟集成。在 API 级别，这是 `MOCK` 集成类型。通常，如果您的 API 尚未最终确定，但您想生成 API 响应以便不妨碍相关团队进行测试，则可使用 `MOCK` 集成。对于 `OPTION` 方法，API Gateway 将 `MOCK` 集成设置为默认值以便为应用的 API 资源返回支持 CORS 的标头。

**设置模拟集成**

1. 在**资源**窗格中，选择**创建方法**。

1. 对于**方法类型**，选择一种 HTTP 方法。

1. 对于**集成类型**，选择**模拟**。

1. （可选）您可以使用以下下拉菜单配置方法请求设置。选择**方法请求设置**并配置您的方法请求。有关更多信息，请参阅[在 API Gateway 控制台中编辑 API Gateway 方法请求](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)的步骤 3。

   您也可以在创建方法后配置方法请求设置。

1. 选择**创建方法**。

# 在 API Gateway 中设置集成响应
<a name="api-gateway-integration-settings-integration-response"></a>

 对于非代理集成，您必须设置至少一个集成响应，并使其作为默认响应，将后端返回的结果传递到客户端。您可以选择按原样传递结果，或者在具有不同格式时，将集成响应数据转换为方法响应数据。

对于代理集成，API Gateway 会自动将后端输出传递到客户端作为 HTTP 响应。您无需设置集成响应或方法响应。

要设置集成响应，您可以执行以下必需任务和 （可选） 任务：

1.  指定集成响应数据要映射到的方法响应的 HTTP 状态代码。该项为必填项。

1.  定义正则表达式以选择要由此集成响应表示的后端输出。如果您将此项留空，则响应为拥有捕获任何尚未配置响应的默认响应。

1.  如果需要，声明由键/值对组成的映射，用于将指定的集成响应参数映射到指定的方法响应参数。

1. 如果需要，请添加正文映射模板来将指定集成响应负载转换为指定方法响应负载。

1.  如果需要，指定如何处理二进制负载的类型转换。

集成响应是封装了后端响应的 HTTP 响应。对于 HTTP 端点，后端响应是 HTTP 响应。集成响应状态代码可以采用后端返回的状态代码，集成响应正文是后端返回的负载。对于 Lambda 端点，后端响应是从 Lambda 函数返回的输出。借助 Lambda 集成，Lambda 函数输出作为 `200 OK` 响应返回。负载可以包含 JSON 数据格式的结果，包括 JSON 字符串或 JSON 对象，或者作为 JSON 对象的错误消息。您可以将正则表达式分配到 [selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern) 属性，以将错误响应映射到适当的 HTTP 错误响应。有关 Lambda 函数错误响应的更多信息，请参阅[处理 API Gateway 中的 Lambda 错误](handle-errors-in-lambda-integration.md)。对于 Lambda 代理集成，Lambda 函数必须返回以下格式的输出：

```
{
    statusCode: "...",            // a valid HTTP status code
    headers: { 
        custom-header: "..."      // any API-specific custom header
    },
    body: "...",                  // a JSON string.
    isBase64Encoded:  true|false  // for binary support
}
```

不需要将 Lambda 函数响应映射到其正确的 HTTP 响应。

要将结果返回到客户端，请设置集成响应将端点响应按原样传递到对应的方法响应。或者，您可以将端点响应数据映射到方法响应数据。可以映射的响应数据包括响应状态代码、响应标头参数和响应正文。如果没有为返回的状态代码定义方法响应，API Gateway 返回 500 错误。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。



# 针对 API Gateway 中的 REST API 的 Lambda 集成
<a name="set-up-lambda-integrations"></a>

 您可以使用 Lambda 代理集成或 Lambda 非代理（自定义）集成将 API 方法与 Lambda 函数集成。

在 Lambda 代理集成中，所需的设置非常简单。将集成的 HTTP 方法设置为 POST，将集成端点 URI 指向特定 Lambda 函数的 Lambda 函数调用操作的 ARN，并授予 API Gateway 代表您调用 Lambda 函数的权限。

在 Lambda 非代理集成中，除了执行代理集成设置步骤，您还需要指定如何将传入请求数据映射到集成请求以及如何将生成的集成响应数据映射到方法响应。

**Topics**
+ [API Gateway 中的 Lambda 代理集成](set-up-lambda-proxy-integrations.md)
+ [在 API Gateway 中设置 Lambda 自定义集成](set-up-lambda-custom-integrations.md)
+ [设置后端 Lambda 函数的异步调用](set-up-lambda-integration-async.md)
+ [处理 API Gateway 中的 Lambda 错误](handle-errors-in-lambda-integration.md)

# API Gateway 中的 Lambda 代理集成
<a name="set-up-lambda-proxy-integrations"></a>

以下部分介绍如何使用 Lambda 代理集成。

**Topics**
+ [了解 API Gateway Lambda 代理集成](#api-gateway-create-api-as-simple-proxy)
+ [支持多值标头和查询字符串参数](#apigateway-multivalue-headers-and-parameters)
+ [用于代理集成的 Lambda 函数的输入格式](#api-gateway-simple-proxy-for-lambda-input-format)
+ [用于代理集成的 Lambda 函数的输出格式](#api-gateway-simple-proxy-for-lambda-output-format)
+ [使用 AWS CLI 为 API Gateway 设置 Lambda 代理集成](set-up-lambda-proxy-integration-using-cli.md)
+ [使用 OpenAPI 定义设置具有 Lambda 代理集成的代理资源](api-gateway-set-up-lambda-proxy-integration-on-proxy-resource.md)

## 了解 API Gateway Lambda 代理集成
<a name="api-gateway-create-api-as-simple-proxy"></a>

Amazon API Gateway Lambda 代理集成是通过设置单个 API 方法来构建 API 的简单、强大且灵活的机制。Lambda 代理集成允许客户端调用后端的单个 Lambda 函数。该函数可访问其他AWS服务的许多资源或功能，包括调用其他 Lambda 函数。

 在 Lambda 代理集成中，当客户端提交 API 请求时，API Gateway 将[事件对象](#api-gateway-simple-proxy-for-lambda-input-format)传递给集成的 Lambda 函数，但不会保留请求参数的顺序。此[请求数据](#api-gateway-simple-proxy-for-lambda-input-format)包括请求标头、查询字符串参数、URL 路径变量、负载和 API 配置数据。配置数据可以包括当前部署阶段名称、阶段变量、用户身份或授权上下文（如果有）。后端 Lambda 函数会对传入请求数据进行解析，以确定要返回的响应。要使 API Gateway 将 Lambda 输出作为 API 响应传递给客户端，Lambda 函数必须返回[此格式](#api-gateway-simple-proxy-for-lambda-output-format)的结果。

 因为 API Gateway 不过多地在 Lambda 代理集成的客户端和后端 Lambda 函数之间进行干预，所以客户端和集成的 Lambda 函数可以适应彼此的变化而不破坏 API 的现有集成设置。要实现这一点，客户端必须遵循后端 Lambda 函数所制定的应用程序协议。

 您可以为任何 API 方法设置 Lambda 代理集成。但是，当为涉及通用代理资源的 API 方法配置 Lambda 代理集成时，该集成更加有效。通用代理资源可由 `{proxy+}` 的特殊模板化路径变量和/或“捕获全部”`ANY` 方法占位符表示。客户端可以在传入请求中将输入作为请求参数或适用负载传递给后端 Lambda 函数。请求参数包括标头、URL 路径变量、查询字符串参数和适用负载。集成的 Lambda 函数会在处理请求之前验证所有输入源，如果缺少任何必需的输入，则会使用有意义的错误消息向客户端做出响应。

 在调用与通用 HTTP 方法 `ANY` 和通用资源 `{proxy+}` 集成的 API 方法时，客户端会使用特定 HTTP 方法而非 `ANY` 来提交请求。客户端还指定特定 URL 路径而非 `{proxy+}`，并包含任何所需的标头、查询字符串参数或适用负载。

 以下列表总结了使用 Lambda 代理集成的不同 API 方法的运行时行为：
+ `ANY /{proxy+}`：客户端必须选择特定 HTTP 方法，必须设置特定资源路径层次结构，并可以设置任何标头、查询字符串参数和适用负载以将数据作为输入传递给集成的 Lambda 函数。
+ `ANY /res`：客户端必须选择特定 HTTP 方法，并可以设置任何标头、查询字符串参数和适用负载以将数据作为输入传递给集成的 Lambda 函数。
+ `GET|POST|PUT|... /{proxy+}`：客户端可以设置特定资源路径层次结构、任何标头、查询字符串参数和适用负载以将数据作为输入传递给集成的 Lambda 函数。
+  `GET|POST|PUT|... /res/{path}/...`：客户端必须选择特定路径分段（针对 `{path}` 变量），并可以设置任何请求标头、查询字符串参数和适用负载以将输入数据传递给集成的 Lambda 函数。
+  `GET|POST|PUT|... /res`：客户端可以选择任何请求标头、查询字符串参数和适用负载以将输入数据传递给集成的 Lambda 函数。

 代理资源 `{proxy+}` 和自定义资源 `{custom}` 都表示为模板化路径变量。但是 `{proxy+}` 可以指路径层次结构中的任何资源，而 `{custom}` 只能指特定路径分段。例如，一个杂货店可以按品类名称、农产品类别和产品类型整理其上线产品库存。然后，该杂货店的网站可以通过自定义资源的以下模板化路径变量来表示可用产品：`/{department}/{produce-category}/{product-type}`。例如，通过 `/produce/fruit/apple` 来表示苹果，通过 `/produce/vegetables/carrot` 来表示胡萝卜。它还可以使用 `/{proxy+}` 来表示客户在其在线商店中购物时可以搜索的任何品类、任何农产品类别或任何产品类型。例如，`/{proxy+}` 可以指以下任一项：
+ `/produce`
+ `/produce/fruit`
+ `/produce/vegetables/carrot`

 要让客户搜索任何可用产品、其农产品类别和关联的商店品类，您可以公开具有只读权限的单个方法 `GET /{proxy+}`。同样地，要允许主管更新 `produce` 品类的库存，您可以设置另一个具有读/写权限的单个方法 `PUT /produce/{proxy+}`。要允许出纳员更新蔬菜的流水式总计，您可以设置一个具有读/写权限的 `POST /produce/vegetables/{proxy+}` 方法。要让商店经理对任何可用产品执行任何可能的操作，在线商店开发人员可以公开具有读/写权限的 `ANY /{proxy+}` 方法。任何情况下，在运行时，客户或员工都必须选择所选品类中给定类型的特定产品、所选品类中的特定农产品类别或特定品类。



有关设置 API Gateway 代理集成的更多信息，请参阅 [设置具有代理资源的代理集成](api-gateway-set-up-simple-proxy.md)。

 代理集成要求客户端更详细地了解后端要求。因此，要确保最佳的应用程序性能和用户体验，后端开发人员必须清楚地向客户端开发人员表明后端的要求，并在不符合要求时提供可靠的错误反馈机制。

## 支持多值标头和查询字符串参数
<a name="apigateway-multivalue-headers-and-parameters"></a>

API Gateway 支持多个具有相同名称的标头和查询字符串参数。多值标头以及单值标头和参数可以组合使用相同的请求和响应。有关更多信息，请参阅 [用于代理集成的 Lambda 函数的输入格式](#api-gateway-simple-proxy-for-lambda-input-format) 和 [用于代理集成的 Lambda 函数的输出格式](#api-gateway-simple-proxy-for-lambda-output-format)。

## 用于代理集成的 Lambda 函数的输入格式
<a name="api-gateway-simple-proxy-for-lambda-input-format"></a>

使用 Lambda 代理集成，API Gateway 可以将整个客户端请求映射到后端 Lambda 函数的输入 `event` 参数：以下示例显示了 API Gateway 发送到 Lambda 代理集成的事件的结构。

在本例中，我们假设对 API Gateway 的调用为以下内容：

```
curl 'https://a1b2c3.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter2=value1&parameter2=value2&parameter3=value1,value2' -H 'header1: value1' -H 'header2: value1' -H 'header2: value2' -H 'header3: value1,value2'
```

输出内容如下所示：

```
{
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
      "header1": "value1",
      "header2": "value2",
      "header3": "value1,value2"
  },
  "multiValueHeaders": {
    "header1": ["value1"],
    "header2": ["value1","value2"],
    "header3": ["value1,value2"]
  },
  "queryStringParameters": {
      "parameter1": "value1",
      "parameter2": "value2",
      "parameter3": "value1,value2"
  },
  "multiValueQueryStringParameters": {
    "parameter1": ["value1"],
    "parameter2": ["value1","value2"],
    "parameter3": ["value1,value2"]
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "id",
    "authorizer": {
      "claims": null,
      "scopes": null
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "extendedRequestId": "request-id",
    "httpMethod": "GET",
    "identity": {
      "accessKey": null,
      "accountId": null,
      "caller": null,
      "cognitoAuthenticationProvider": null,
      "cognitoAuthenticationType": null,
      "cognitoIdentityId": null,
      "cognitoIdentityPoolId": null,
      "principalOrgId": null,
      "sourceIp": "IP",
      "user": null,
      "userAgent": "user-agent",
      "userArn": null,
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "path": "/my/path",
    "protocol": "HTTP/1.1",
    "requestId": "id=",
    "requestTime": "04/Mar/2020:19:15:17 +0000",
    "requestTimeEpoch": 1583349317135,
    "resourceId": null,
    "resourcePath": "/my/path",
    "stage": "$default"
  },
  "pathParameters": null,
  "stageVariables": null,
  "body": "Hello from Lambda!",
  "isBase64Encoded": false
}
```

**注意**  
在输入中：  
`headers` 密钥只能包含单值标头。
`multiValueHeaders` 密钥可以包含多值标头以及单值标头。
如果您指定 `headers` 和 `multiValueHeaders` 的值，API Gateway 会将它们合并为一个列表。如果两者都指定了相同的键/值对，则合并列表中只会出现 `multiValueHeaders` 的值。

在后端 Lambda 函数的输入中，`requestContext` 对象是键/值对的映射。在每对中，键为 [\$1context](api-gateway-mapping-template-reference.md#context-variable-reference) 变量属性的名称，值为该属性的值。API Gateway 可能会向映射中添加新键。

根据启用的功能，不同 API 的 `requestContext` 映射可能有所不同。例如，在上述示例中，未指定任何授权类型，因此不存在任何 `$context.authorizer.*` 或 `$context.identity.*` 属性。当指定某个授权类型时，这会导致 API Gateway 将授权用户信息传递给 `requestContext.identity` 对象中的集成端点，如下所示：
+ 当授权类型为 `AWS_IAM` 时，授权用户信息包括 `$context.identity.*` 属性。
+ 当授权类型为 `COGNITO_USER_POOLS`（Amazon Cognito 授权方）时，授权用户信息包括 `$context.identity.cognito*` 和 `$context.authorizer.claims.*`。
+ 当授权类型为 `CUSTOM`（Lambda 授权方）时，授权用户信息包括 `$context.authorizer.principalId` 及其他适用的 `$context.authorizer.*` 属性。

## 用于代理集成的 Lambda 函数的输出格式
<a name="api-gateway-simple-proxy-for-lambda-output-format"></a>

在 Lambda 代理集成中，API Gateway 需要后端 Lambda 函数根据以下 JSON 格式返回输出：

```
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}
```

在输出中：
+ 如果不返回任何额外的响应标头，则可以不指定 `headers` 和 `multiValueHeaders` 键。
+ `headers` 密钥只能包含单值标头。
+ `multiValueHeaders` 密钥可以包含多值标头以及单值标头。您可以使用 `multiValueHeaders` 密钥来指定所有额外的标头，包括任何单值标头。
+ 如果您指定 `headers` 和 `multiValueHeaders` 的值，API Gateway 会将它们合并为一个列表。如果两者都指定了相同的键/值对，则合并列表中只会出现 `multiValueHeaders` 的值。

要为 Lambda 代理集成启用 CORS，您必须将 `Access-Control-Allow-Origin:domain-name` 添加到输出 `headers`。`domain-name` 可以为 `*`，表示任意域名。输出 `body` 作为方法响应负载封送到前端。如果 `body` 是二进制 blob，您可以通过将 `isBase64Encoded` 设置为 `true` 并将 `*/*` 配置为**二进制媒体类型**来将其编码为采用 Base64 编码的字符串。否则，您可以将其设置为 `false` 或不进行指定。

**注意**  
有关启用二进制文件支持的更多信息，请参阅[使用 API Gateway 控制台启用二进制支持](api-gateway-payload-encodings-configure-with-console.md)。有关示例 Lambda 函数，请参阅 [从 API Gateway 中的 Lambda 代理集成返回二进制媒体](lambda-proxy-binary-media.md)。

如果函数输出属于其他格式，则 API Gateway 将返回 `502 Bad Gateway` 错误响应。

要在 Node.js 的 Lambda 函数中返回响应，您可以使用如下所示的命令：
+ 要返回成功的结果，请调用 `callback(null, {"statusCode": 200, "body": "results"})`。
+ 要引发异常，请调用 `callback(new Error('internal server error'))`。
+ 对于客户端错误（例如，如果缺少必需参数），可以调用 `callback(null, {"statusCode": 400, "body": "Missing parameters of ..."})` 以返回错误而不引发异常。

在 Node.js 的 Lambda `async` 函数中，等效的语法为：
+ 要返回成功的结果，请调用 `return {"statusCode": 200, "body": "results"}`。
+ 要引发异常，请调用 `throw new Error("internal server error")`。
+ 对于客户端错误（例如，如果缺少必需参数），可以调用 `return {"statusCode": 400, "body": "Missing parameters of ..."}` 以返回错误而不引发异常。

# 使用 AWS CLI 为 API Gateway 设置 Lambda 代理集成
<a name="set-up-lambda-proxy-integration-using-cli"></a>

在此部分中，我们将介绍如何使用 AWS CLI 设置 API 与 Lambda 代理集成。有关使用 API Gateway 控制台配置与 Lambda 代理集成的代理资源的详细说明，请参阅 [教程：利用 Lambda 代理集成创建 REST API](api-gateway-create-api-as-simple-proxy-for-lambda.md)。

例如，我们使用以下示例 Lambda 函数作为 API 的后端：

```
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
};
```

将这一点与[在 API Gateway 中设置 Lambda 自定义集成](set-up-lambda-custom-integrations.md)中的 Lambda 自定义集成设置对比，对此 Lambda 函数的输入可能出现在请求参数和正文中。您可以有更多的自主度来允许客户端传递相同的输入数据。在这里，客户端可以将欢迎者的姓名作为查询字符串参数、标题或正文属性传递。该函数还支持 Lambda 自定义集成。API 设置更简单。您完全无需配置方法响应或集成响应。

**使用 AWS CLI 设置 Lambda 代理集成**

1. 使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建 API：

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   输出将与以下内容类似：

   ```
   {
       "name": "HelloWorldProxy (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   在本示例中，您使用了 API `id`（`te6si5ach7`）和 `rootResourceId`（`krznpq9xpg`）。

1. 使用以下 [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 命令创建 `/greeting` 的 API Gateway [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)：

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part {proxy+}
   ```

   输出将与以下内容类似：

   ```
   {
       "path": "/{proxy+}", 
       "pathPart": "{proxy+}", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   在下一步中，您可以使用 `{proxy+}` 资源的 `id` 值（`2jf6xt`），在 `/{proxy+}` 资源上创建方法。

1. 使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 创建 `ANY /{proxy+}` 的 `ANY` 方法请求：

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method ANY \
          --authorization-type "NONE"
   ```

   输出将与以下内容类似：

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "ANY", 
       "authorizationType": "NONE"
   }
   ```

   此 API 方法允许客户端从后端的 Lambda 函数接收或发送问候语。

1. 使用以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 命令，设置 `ANY /{proxy+}` 方法与名为 `HelloWorld` 的 Lambda 函数的集成。在提供 `greeter` 参数时，此函数使用消息 `"Hello, {name}!"` 响应请求，在未设置查询字符串参数时使用 `"Hello, World!"` 响应。

   ```
   aws apigateway put-integration \
         --rest-api-id te6si5ach7 \
         --resource-id 2jf6xt \
         --http-method ANY \
         --type AWS_PROXY \
         --integration-http-method POST \
         --uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:HelloWorld/invocations \
         --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```
**重要**  
对于 Lambda 集成，根据[函数调用的 Lambda 服务操作规范](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)，您必须为集成请求使用 HTTP 方法 `POST`。`apigAwsProxyRole` 的 IAM 角色必须具有策略，允许 `apigateway` 服务调用 Lambda 函数。有关 IAM 权限的更多信息，请参阅[用于调用 API 的 API Gateway 权限模型](permissions.md#api-gateway-control-access-iam-permissions-model-for-calling-api)。

   输出将与以下内容类似：

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:1234567890:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "cacheNamespace": "vvom7n", 
       "credentials": "arn:aws:iam::1234567890:role/apigAwsProxyRole", 
       "type": "AWS_PROXY"
   }
   ```

   您不用为 `credentials` 提供 IAM 角色，而是可以使用 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令添加基于资源的权限。这是 API Gateway 控制台的功能。

1. 使用以下 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 命令，将 API 部署到 `test` 阶段：

   ```
   aws apigateway create-deployment  \
         --rest-api-id te6si5ach7 \
         --stage-name test
   ```

1. 在终端中使用以下 cURL 命令测试 API。

   使用查询字符串参数 `?greeter=jane` 调用 API：

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=jane'
   ```

   使用 `greeter:jane` 的标头参数调用 API：

   ```
   curl -X GET https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -H 'greeter: jane'
   ```

   使用 `{"greeter":"jane"}` 的正文调用 API：

   ```
   curl -X POST https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -d '{ "greeter": "jane" }'
   ```

   在所有情况下，输出为具有以下响应正文的 200 响应：

   ```
   Hello, jane!
   ```

# 使用 OpenAPI 定义设置具有 Lambda 代理集成的代理资源
<a name="api-gateway-set-up-lambda-proxy-integration-on-proxy-resource"></a>

要设置具有 Lambda 代理集成类型的代理资源，请创建一个具有“贪婪”路径参数（例如，`/parent/{proxy+}`）的 API 资源，并将该资源与 `arn:aws:lambda:us-west-2:123456789012:function:SimpleLambda4ProxyResource` 方法上的 Lambda 函数后端（例如，`ANY`）集成。“贪婪”路径参数必须位于 API 资源路径的末尾。与处理非代理资源一样，您可以通过使用 API Gateway 控制台、导入 OpenAPI 定义文件或直接调用 API Gateway REST API 来设置代理资源。

以下 OpenAPI API 定义文件显示了一个 API 的示例，该 API 具有与名为 `SimpleLambda4ProxyResource` 的 Lambda 函数集成的代理资源。

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-09-12T17:50:37Z",
      "title": "ProxyIntegrationWithLambda"
   },
   "paths": {
      "/{proxy+}": {
         "x-amazon-apigateway-any-method": {
            "parameters": [
               {
                  "name": "proxy",
                  "in": "path",
                  "required": true,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {},
            "x-amazon-apigateway-integration": {
               "responses": {
                  "default": {
                     "statusCode": "200"
                  }
               },
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "POST",
               "cacheNamespace": "roq9wj",
               "cacheKeyParameters": [
                  "method.request.path.proxy"
               ],
               "type": "aws_proxy"
            }
         }
      }
   },
   "servers": [
      {
         "url": "https://gy415nuibc.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/testStage"
            }
         }
      }
   ]
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-12T17:50:37Z",
    "title": "ProxyIntegrationWithLambda"
  },
  "host": "gy415nuibc.execute-api.us-east-1.amazonaws.com",
  "basePath": "/testStage",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {},
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "cacheNamespace": "roq9wj",
          "cacheKeyParameters": [
            "method.request.path.proxy"
          ],
          "type": "aws_proxy"
        }
      }
    }
  }
}
```

------

在 Lambda 代理集成中，在运行时，API Gateway 将传入请求映射到 Lambda 函数的输入 `event` 参数中。该输入包含请求方法、路径、标头、任何字符串参数、任何负载、关联的上下文以及定义的任何阶段变量。输入格式在[用于代理集成的 Lambda 函数的输入格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format)中说明。为了让 API Gateway 将 Lambda 输出成功映射到 HTTP 响应，Lambda 函数必须按照[用于代理集成的 Lambda 函数的输出格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format)中说明的格式输出结果。

在通过 `ANY` 方法实现代理资源的 Lambda 代理集成的过程中，单个后端 Lambda 函数充当通过代理资源的所有请求的事件处理程序。例如，要记录流量模式，您可以让移动设备提交一个代理资源的 URL 路径中附带 `/state/city/street/house` 的请求，从而发送包含州、城市、街道和建筑信息的位置信息。然后，后端 Lambda 函数可以分析 URL 路径并将位置元组插入 DynamoDB 表。

# 在 API Gateway 中设置 Lambda 自定义集成
<a name="set-up-lambda-custom-integrations"></a>

 为了显示如何设置 Lambda 自定义或非代理集成，我们创建了一个 API Gateway API，用于公开 `GET /greeting?greeter={name}` 方法来调用 Lambda 函数。为您的 API 使用以下 Lambda 函数示例之一。

使用以下 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;
};
```

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

```
import json


def lambda_handler(event, context):
    print(event)
    res = {
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    }

    if event['greeter'] == "":
        res['body'] = "Hello, World"
    elif (event['greeter']):
        res['body'] = "Hello, " + event['greeter'] + "!"
    else:
        raise Exception('Missing the required greeter parameter.')

    return res
```

------

在 `greeter` 参数值为非空字符串时，该函数使用消息 `"Hello, {name}!"` 进行响应。如果 `greeter` 值是空字符串，则返回消息 `"Hello, World!"`。如果传入请求中未设置 greeter 参数，则返回错误消息 `"Missing the required greeter parameter."`。我们将函数命名为 `HelloWorld`。

您可以在 Lambda 控制台中或使用 AWS CLI 创建它。在此部分中，我们使用以下 ARN 引用此函数：

```
arn:aws:lambda:us-east-1:123456789012:function:HelloWorld
```

在后端设置了 Lambda 函数之后，继续设置 API。<a name="set-up-lambda-custom-integration-using-cli"></a>

**使用 AWS CLI 设置 Lambda 自定义集成**

1. 使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建 API：

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   输出将与以下内容类似：

   ```
   {
       "name": "HelloWorld (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   在本示例中，您使用了 API `id`（`te6si5ach7`）和 `rootResourceId`（`krznpq9xpg`）。

1. 使用以下 [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 命令创建 `/greeting` 的 API Gateway [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)：

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part greeting
   ```

   输出将与以下内容类似：

   ```
   {
       "path": "/greeting", 
       "pathPart": "greeting", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   在下一步中，您可以使用 `greeting` 资源的 `id` 值（`2jf6xt`），在 `/greeting` 资源上创建方法。

1. 使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建 `GET /greeting?greeter={name}` 的 API 方法请求：

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method GET \
          --authorization-type "NONE" \
          --request-parameters method.request.querystring.greeter=false
   ```

   输出将与以下内容类似：

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "GET", 
       "authorizationType": "NONE", 
       "requestParameters": {
           "method.request.querystring.greeter": false
       }
   }
   ```

   此 API 方法允许客户端从后端的 Lambda 函数接收问候语。此 `greeter` 参数是可选的，因为后端应处理匿名调用方或自识别调用方。

1. 使用以下 [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) 命令，设置对 `GET /greeting?greeter={name}` 的方法请求的 `200 OK` 响应：

   ```
   aws apigateway put-method-response \
           --rest-api-id te6si5ach7 \ 
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200
   ```

   

1. 使用以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 命令，设置 `GET /greeting?greeter={name}` 方法与名为 `HelloWorld` 的 Lambda 函数的集成。在提供 `greeter` 参数时，函数使用消息 `"Hello, {name}!"` 响应请求，在未设置查询字符串参数时使用 `"Hello, World!"` 响应。

   ```
   aws apigateway put-integration \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --type AWS \
           --integration-http-method POST \
           --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations \
           --request-templates '{"application/json":"{\"greeter\":\"$input.params('greeter')\"}"}' \
           --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```

   此处提供的映射模板转换为 JSON 负载 `greeter` 属性的 `greeter` 查询字符串参数。这么做是必要的，因为对 Lambda 函数的输入必须在正文中表示。
**重要**  
对于 Lambda 集成，根据[函数调用的 Lambda 服务操作规范](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)，您必须为集成请求使用 HTTP 方法 `POST`。`uri` 参数是函数调用操作的 ARN。  
输出将与以下内容类似：

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "requestTemplates": {
           "application/json": "{\"greeter\":\"$input.params('greeter')\"}"
       }, 
       "cacheNamespace": "krznpq9xpg", 
       "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", 
       "type": "AWS"
   }
   ```

   `apigAwsProxyRole` 的 IAM 角色必须具有策略，允许 `apigateway` 服务调用 Lambda 函数。不同于为 `credentials` 提供 IAM 角色，您可以调用 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令以添加基于资源的权限。这就是 API Gateway 控制台添加这些权限的方式。

1. 使用以下 [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) 命令设置集成响应，用于将 Lambda 函数输出传递到客户端作为 `200 OK` 方法响应：

   ```
    aws apigateway put-integration-response \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200 \
           --selection-pattern ""
   ```

   将 selection-pattern 设置为空字符串时，`200 OK` 响应是默认值。

   输出将与以下内容类似：

   ```
    {
       "selectionPattern": "", 
       "statusCode": "200"
   }
   ```

1. 使用以下 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 命令，将 API 部署到 `test` 阶段：

   ```
   aws apigateway create-deployment \
           --rest-api-id te6si5ach7 \
           --stage-name test
   ```

1.  在终端中使用以下 cURL 命令测试 API：

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=me' \
     -H 'authorization: AWS4-HMAC-SHA256 Credential={access_key}/20171020/us-west-2/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=f327...5751'
   ```

# 设置后端 Lambda 函数的异步调用
<a name="set-up-lambda-integration-async"></a>

在 Lambda 非代理（自定义）集成中，默认情况下后端 Lambda 函数是同步调用的。这是大多数 REST API 操作的预期行为。但是，某些应用程序通常需要由某个单独的后端组件进行异步执行（如分批操作或长延迟操作）才能运行。在这种情况下，后端 Lambda 函数将进行异步调用，而且前端 REST API 方法不会返回结果。

您可以通过将 `'Event'` 指定为 [Lambda 调用类型](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html)，为要异步调用的 Lambda 非代理集成配置 Lambda 函数。按如下所示完成此操作：

## 在 API Gateway 控制台中配置 Lambda 异步调用
<a name="asynchronous-invocation-console-examples"></a>

要使所有调用均为异步，请执行以下操作：
+ 在**集成请求**中，添加使用静态值 `'Event'` 的 `X-Amz-Invocation-Type` 标头。

要让客户端决定调用为异步还是同步，请执行以下操作：

1. 在**方法请求**中，添加 `InvocationType` 标头。

1. 在**集成请求**中，添加使用映射表达式 `method.request.header.InvocationType` 的 `X-Amz-Invocation-Type` 标头。

1. 在 API 请求中，对于异步调用，客户端可以包含 `InvocationType: Event` 标头，对于同步调用则可以包含 `InvocationType: RequestResponse`。

## 使用 OpenAPI 配置 Lambda 异步调用
<a name="asynchronous-invocation-OpenAPI-examples"></a>

要使所有调用均为异步，请执行以下操作：
+  将 `X-Amz-Invocation-Type` 标头添加到 **x-amazon-apigateway-integration** 部分。

  ```
  "x-amazon-apigateway-integration" : {
            "type" : "aws",
            "httpMethod" : "POST",
            "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
            "responses" : {
              "default" : {
                "statusCode" : "200"
              }
            },
            "requestParameters" : {
              "integration.request.header.X-Amz-Invocation-Type" : "'Event'"
            },
            "passthroughBehavior" : "when_no_match",
            "contentHandling" : "CONVERT_TO_TEXT"
          }
  ```

要让客户端决定调用为异步还是同步，请执行以下操作：

1.  在任何 [OpenAPI 路径项对象](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject)上添加以下标头。

   ```
   "parameters" : [ {
   "name" : "InvocationType",
   "in" : "header",
   "schema" : {
     "type" : "string"
   }
   } ]
   ```

1.  将 `X-Amz-Invocation-Type` 标头添加到 **x-amazon-apigateway-integration** 部分。

   ```
   "x-amazon-apigateway-integration" : {
             "type" : "aws",
             "httpMethod" : "POST",
             "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
             "responses" : {
               "default" : {
                 "statusCode" : "200"
               }
             },
             "requestParameters" : {
               "integration.request.header.X-Amz-Invocation-Type" : "method.request.header.InvocationType"
             },
             "passthroughBehavior" : "when_no_match",
             "contentHandling" : "CONVERT_TO_TEXT"
           }
   ```

1.  在 API 请求中，对于异步调用，客户端可以包含 `InvocationType: Event` 标头，对于同步调用则可以包含 `InvocationType: RequestResponse`。

## 使用 CloudFormation 配置 Lambda 异步调用
<a name="asynchronous-invocation-cfn-examples"></a>

以下 CloudFormation 模板显示如何配置 `AWS::ApiGateway::Method` 来进行异步调用。

要使所有调用均为异步，请执行以下操作：

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: "'Event'"
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

要让客户端决定调用为异步还是同步，请执行以下操作：

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      RequestParameters:
        method.request.header.InvocationType: false
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: method.request.header.InvocationType
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

 在 API 请求中，对于异步调用，客户端可以包含 `InvocationType: Event` 标头，对于同步调用则可以包含 `InvocationType: RequestResponse`。

# 处理 API Gateway 中的 Lambda 错误
<a name="handle-errors-in-lambda-integration"></a>

 对于 Lambda 自定义集成，您必须将在集成响应中由 Lambda 返回的错误映射到客户端的标准 HTTP 错误响应。否则，Lambda 错误会默认返回为 `200 OK` 响应，并且结果对于您的 API 用户而言并不直观。

 Lambda 可以返回两种类型的错误：标准错误和自定义错误。在您的 API 中，您必须以不同方式处理这些错误。

 对于 Lambda 代理集成，Lambda 需要返回以下格式的输出：

```
{
  "isBase64Encoded" : "boolean",
  "statusCode": "number",
  "headers": { ... },
  "body": "JSON string"
}
```

在此输出中，`statusCode` 通常为 `4XX` (对于客户端错误) 和 `5XX` (对于服务器错误)。API Gateway 可根据指定的 `statusCode`，通过将 Lambda 错误到 HTTP 错误响应来处理这些错误。要使 API Gateway 将错误类型（例如 `InvalidParameterException`）作为响应的一部分传递给客户端，Lambda 函数必须在 `"X-Amzn-ErrorType":"InvalidParameterException"` 属性中包括标头（例如 `headers`）。

**Topics**
+ [处理 API Gateway 中的标准 Lambda 错误](#handle-standard-errors-in-lambda-integration)
+ [处理 API Gateway 中的自定义 Lambda 错误](#handle-custom-errors-in-lambda-integration)

## 处理 API Gateway 中的标准 Lambda 错误
<a name="handle-standard-errors-in-lambda-integration"></a>

标准的 AWS Lambda 错误具有以下格式:

```
{
  "errorMessage": "<replaceable>string</replaceable>",
  "errorType": "<replaceable>string</replaceable>",
  "stackTrace": [
    "<replaceable>string</replaceable>",
    ...
  ]
}
```

 其中，`errorMessage` 是错误的字符串表达式。`errorType` 是取决于语言的错误或异常类型。`stackTrace` 是一个字符串表达式列表，显示导致发生错误的堆栈跟踪。

 例如，请考虑以下 JavaScript (Node.js) Lambda 函数。

```
export const handler = function(event, context, callback) {
    callback(new Error("Malformed input ..."));
};
```

此函数返回以下标准 Lambda 错误，其中包含 `Malformed input ...` 作为错误消息：

```
{
  "errorMessage": "Malformed input ...",
  "errorType": "Error",
  "stackTrace": [
    "export const handler (/var/task/index.js:3:14)"
  ]
}
```

 同样，请考虑以下 Python Lambda 函数，该函数会引发具有相同 `Exception` 错误消息的 `Malformed input ...`。

```
def lambda_handler(event, context):
    raise Exception('Malformed input ...')
```

 此函数会返回以下标准 Lambda 错误：

```
{
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      3,
      "lambda_handler",
      "raise Exception('Malformed input ...')"
    ]
  ],
  "errorType": "Exception",
  "errorMessage": "Malformed input ..."
}
```

 请注意，`errorType` 和 `stackTrace` 属性值因语言而异。标准错误也适用于作为 `Error` 对象的扩展或 `Exception` 类的子类的任何错误对象。

 要将标准 Lambda 错误映射到方法响应，您必须首先为给定的 Lambda 错误确定 HTTP 状态代码。然后，针对与给定 HTTP 状态代码相关联的 [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 的 `[selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern)` 属性设置正则表达式模式。在 API Gateway 控制台的**集成响应**部分，此 `selectionPattern` 在每个集成响应下方表示为 **Lambda 错误正则表达式**。

**注意**  
API Gateway 使用 Java 模式的正则表达式来响应映射。有关更多信息，请参阅 Oracle 文档中的[模式](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)。

 例如，使用以下 [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) 命令设置新 `selectionPattern` 表达式：

```
aws apigateway put-integration-response --rest-api-id z0vprf0mdh --resource-id x3o5ih --http-method GET --status-code 400 --selection-pattern "Malformed.*" --region us-west-2
```

 确保您还针对 [方法响应](api-gateway-method-settings-method-response.md#setup-method-response-status-code) 设置了相应的错误代码 (`400`)。否则，API Gateway 会在运行时引发一个关于配置无效的错误响应。

**注意**  
 在运行时，API Gateway 将 Lambda 错误的 `errorMessage` 与 `selectionPattern` 属性的正则表达式模式相匹配。当存在匹配时，API Gateway 将返回 Lambda 错误作为相应 HTTP 状态码的 HTTP 响应。如果没有匹配，API Gateway 将返回错误作为默认响应，或者引发配置无效异常（如果未配置默认响应）。  
 针对给定响应数量，将 `selectionPattern` 值设置为 `.*` 会将此响应重置为默认响应。这是因为此类选择模式将匹配所有错误消息，包括 null (即，任何未指定的错误消息)。生成的映射会覆盖默认映射。如果您使用 `.+` 作为选择模式来筛选响应，请注意，它可能与包含换行符（'`\n`）的响应不匹配。

 要使用 `selectionPattern` 更新现有 AWS CLI 值，请调用 [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) 操作，以将 `/selectionPattern` 路径值替换为 `Malformed*` 模式的指定正则表达式。



要使用 API Gateway 控制台设置 `selectionPattern` 表达式，请在设置或更新指定 HTTP 状态代码的集成响应时，在 **Lambda 错误正则表达式**文本框中输入表达式。

## 处理 API Gateway 中的自定义 Lambda 错误
<a name="handle-custom-errors-in-lambda-integration"></a>

 AWS Lambda 允许您返回自定义错误对象作为 JSON 字符串，而不是返回上一部分所述的标准错误。该错误可以是任何有效的 JSON 对象。例如，下面的 JavaScript (Node.js) Lambda 函数会返回自定义错误：

```
export const handler = (event, context, callback) => {
    ...
    // Error caught here:
    var myErrorObj = {
        errorType : "InternalServerError",
        httpStatus : 500,
        requestId : context.awsRequestId,
        trace : {
            "function": "abc()",
            "line": 123,
            "file": "abc.js"
        }
    }
    callback(JSON.stringify(myErrorObj));
};
```

 您必须先将 `myErrorObj` 对象转换为 JSON 字符串，然后才能调用 `callback` 以退出函数。否则，`myErrorObj` 会返回为 `"[object Object]"` 字符串。当您的 API 方法与上述 Lambda 函数集成时，API Gateway 会接收具有以下负载的集成响应：

```
{
    "errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}"
}
```

 与任何集成响应一样，您可以将此错误响应按原样传递至方法响应。或者，您可以使用映射模板将负载转换为另一种格式。例如，针对 `500` 状态代码的方法响应考虑以下正文映射模板：

```
{
    errorMessage: $input.path('$.errorMessage');
}
```

此模板会将包含自定义错误 JSON 字符串的集成响应正文转换为以下方法响应正文。此方法响应正文包含自定义错误 JSON 对象：

```
{
    "errorMessage" : {
        errorType : "InternalServerError",
        httpStatus : 500,
        requestId : context.awsRequestId,
        trace : {
            "function": "abc()",
            "line": 123,
            "file": "abc.js"
        }
    }
};
```

 根据您的 API 要求，您可能需要传递部分或全部自定义错误属性作为方法响应标头参数。为实现这一点，您可以将来自集成响应正文的自定义错误映射应用到方法响应标头。

例如，下面的 OpenAPI 扩展定义了 `errorMessage.errorType`、`errorMessage.httpStatus`、`errorMessage.trace.function` 和 `errorMessage.trace` 属性分别到 `error_type`、`error_status`、`error_trace_function` 和 `error_trace` 标头的映射。

```
"x-amazon-apigateway-integration": {
    "responses": {
        "default": {
          "statusCode": "200",
          "responseParameters": {
            "method.response.header.error_trace_function": "integration.response.body.errorMessage.trace.function",
            "method.response.header.error_status": "integration.response.body.errorMessage.httpStatus",
            "method.response.header.error_type": "integration.response.body.errorMessage.errorType",
            "method.response.header.error_trace": "integration.response.body.errorMessage.trace"
          },
          ...
        }
    }
}
```

 在运行时，API Gateway 会在执行标头映射时反序列化 `integration.response.body` 参数。但是，这种反序列化仅适用于 Lambda 自定义错误响应的“正文到标头”映射，并不适用于使用 `$input.body` 的“正文到正文”映射。使用这些 custom-error-body-to-header 映射，客户端会收到以下标头作为方法响应的一部分，前提是方法请求中声明了 `error_status`、`error_trace`、`error_trace_function` 和 `error_type` 标头。

```
"error_status":"500",
"error_trace":"{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}",
"error_trace_function":"abc()",
"error_type":"InternalServerError"
```

集成响应正文的 `errorMessage.trace` 属性是一个复杂的属性。它会作为 JSON 字符串映射到 `error_trace` 标头。

# 针对 API Gateway 中的 REST API 的 HTTP 集成
<a name="setup-http-integrations"></a>

 您可以使用 HTTP 代理集成或 HTTP 自定义集成将 API 方法与 HTTP 终端节点进行集成。

API Gateway 支持以下终端节点端口：80、443 和 1024-65535。

 借助代理集成，进行设置非常简单。如果不考虑内容编码或缓存，则只需根据后端要求设置 HTTP 方法和 HTTP 终端节点 URI。

 借助自定义集成，进行设置更为复杂。除了执行代理集成设置步骤，还需要指定如何将传入请求数据映射到集成请求以及如何将生成的集成响应数据映射到方法响应。

**Topics**
+ [在 API Gateway 中设置 HTTP 代理集成](#api-gateway-set-up-http-proxy-integration-on-proxy-resource)
+ [在 API Gateway 中设置 HTTP 自定义集成](#set-up-http-custom-integrations)

## 在 API Gateway 中设置 HTTP 代理集成
<a name="api-gateway-set-up-http-proxy-integration-on-proxy-resource"></a>

要设置具有 HTTP 代理集成类型的代理资源，请创建一个具有“贪婪”路径参数（例如，`/parent/{proxy+}`）的 API 资源，并将该资源与 `https://petstore-demo-endpoint.execute-api.com/petstore/{proxy}` 方法上的 HTTP 后端终端节点（例如，`ANY`）集成。“贪婪”路径参数必须位于资源路径的末尾。

与处理非代理资源一样，您可以通过 API Gateway 控制台、导入 OpenAPI 定义文件或直接调用 API Gateway REST API 来设置具有 HTTP 代理集成的代理资源。有关使用 API Gateway 控制台配置与 HTTP 集成的代理资源的详细说明，请参阅 [教程：利用 HTTP 代理集成创建 REST API](api-gateway-create-api-as-simple-proxy-for-http.md)。

以下 OpenAPI 定义文件显示了一个 API 的示例，该 API 具有与 [PetStore](http://petstore-demo-endpoint.execute-api.com/petstore/pets) 网站集成的代理资源。

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-09-12T23:19:28Z",
      "title": "PetStoreWithProxyResource"
   },
   "paths": {
      "/{proxy+}": {
         "x-amazon-apigateway-any-method": {
            "parameters": [
               {
                  "name": "proxy",
                  "in": "path",
                  "required": true,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {},
            "x-amazon-apigateway-integration": {
               "responses": {
                  "default": {
                     "statusCode": "200"
                  }
               },
               "requestParameters": {
                  "integration.request.path.proxy": "method.request.path.proxy"
               },
               "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/{proxy}",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "ANY",
               "cacheNamespace": "rbftud",
               "cacheKeyParameters": [
                  "method.request.path.proxy"
               ],
               "type": "http_proxy"
            }
         }
      }
   },
   "servers": [
      {
         "url": "https://4z9giyi2c1.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/test"
            }
         }
      }
   ]
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-12T23:19:28Z",
    "title": "PetStoreWithProxyResource"
  },
  "host": "4z9giyi2c1.execute-api.us-east-1.amazonaws.com",
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {},
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/{proxy}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "ANY",
          "cacheNamespace": "rbftud",
          "cacheKeyParameters": [
            "method.request.path.proxy"
          ],
          "type": "http_proxy"
        }
      }
    }
  }
}
```

------

在本示例中，代理资源的 `method.request.path.proxy` 路径参数上声明了一个缓存键。这是您使用 API Gateway 控制台创建 API 时的默认设置。API 的基本路径 (`/test`，与一个阶段对应) 映射到网站的 PetStore 页面 (`/petstore`)。单个集成请求可以使用 API 的“贪婪”路径变量和“捕获所有”的 `ANY` 方法镜像整个 PetStore 网站。建立镜像的过程如下所示。
+ **将 `ANY` 设置为 `GET` 并将 `{proxy+}` 设置为 `pets`**

  从前端发起的方法请求：

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets HTTP/1.1
  ```

  发送到后端的集成请求：

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets HTTP/1.1
  ```

  `ANY` 方法和代理资源的运行时实例都是有效的。此调用将返回一个 `200 OK` 响应以及包含从后端返回的第一批宠物的负载。
+ **将 `ANY` 设置为 `GET` 并将 `{proxy+}` 设置为 `pets?type=dog`**

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets?type=dog HTTP/1.1
  ```

  发送到后端的集成请求：

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets?type=dog HTTP/1.1
  ```

  `ANY` 方法和代理资源的运行时实例都是有效的。此调用将返回一个 `200 OK` 响应以及包含从后端返回的第一批指定宠物狗的负载。
+ **将 `ANY` 设置为 `GET` 并将 `{proxy+}` 设置为 `pets/{petId}`**

  从前端发起的方法请求：

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets/1 HTTP/1.1
  ```

  发送到后端的集成请求：

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets/1 HTTP/1.1
  ```

  `ANY` 方法和代理资源的运行时实例都是有效的。此调用将返回一个 `200 OK` 响应以及包含从后端返回的指定宠物的负载。
+ **将 `ANY` 设置为 `POST` 并将 `{proxy+}` 设置为 `pets`**

  从前端发起的方法请求：

  ```
  POST https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets HTTP/1.1
  Content-Type: application/json
  Content-Length: ...
  
  {
    "type" : "dog",
    "price" : 1001.00
  }
  ```

  发送到后端的集成请求：

  ```
  POST http://petstore-demo-endpoint.execute-api.com/petstore/pets HTTP/1.1
  Content-Type: application/json
  Content-Length: ...
  
  {
    "type" : "dog",
    "price" : 1001.00
  }
  ```

  `ANY` 方法和代理资源的运行时实例都是有效的。此调用将返回一个 `200 OK` 响应以及包含从后端返回的新创建的宠物的负载。
+ **将 `ANY` 设置为 `GET` 并将 `{proxy+}` 设置为 `pets/cat`**

  从前端发起的方法请求：

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets/cat
  ```

  发送到后端的集成请求：

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets/cat
  ```

  代理资源路径的运行时实例与后端终端节点不对应，且生成的请求无效。因此，系统会返回 `400 Bad Request` 响应，并显示以下错误消息。

  ```
  {
    "errors": [
      {
        "key": "Pet2.type",
        "message": "Missing required field"
      },
      {
        "key": "Pet2.price",
        "message": "Missing required field"
      }
    ]
  }
  ```
+ **将 `ANY` 设置为 `GET` 并将 `{proxy+}` 设置为 `null`**

  从前端发起的方法请求：

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test
  ```

  发送到后端的集成请求：

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets
  ```

  目标资源是代理资源的父资源，但未在该资源上的 API 中定义 `ANY` 方法的运行时实例。因此，此 `GET` 请求将返回一个 `403 Forbidden` 响应，而 API Gateway 返回 `Missing Authentication Token` 错误消息。如果 API 在父资源 (`ANY`) 上公开 `GET` 或 `/` 方法，则此调用将返回一个 `404 Not Found` 响应，同时从后端返回 `Cannot GET /petstore` 消息。

对于任何客户端请求，如果目标终端节点 URL 无效或 HTTP 命令动词有效但不受支持，则后端将返回 `404 Not Found` 响应。对于不受支持的 HTTP 方法，系统会返回 `403 Forbidden` 响应。

## 在 API Gateway 中设置 HTTP 自定义集成
<a name="set-up-http-custom-integrations"></a>

 使用 HTTP 自定义集成（也称为非代理集成），您可以更好地控制在 API 方法和 API 集成之间传递哪些数据以及如何传递数据。您可以使用数据映射执行此操作。

作为方法请求设置的一部分，您需要设置 [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html)（方法）资源中的 [requestParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#requestParameters) 属性。这会声明对于从客户端预配置的方法请求参数，哪些要先映射到集成请求参数或适用的正文属性，然后再分派到后端。然后，作为集成请求设置的一部分，在相应的 [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)（集成）资源上设置 [requestParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#requestParameters) 属性，以指定参数到参数的映射。您还要设置 [requestTemplates](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#requestTemplates) 属性，以指定映射模板，为每个支持的内容类型设置一个映射模板。映射模板将方法请求参数或正文映射到集成请求正文。

 同样，作为方法响应设置的一部分，您可以在 [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) 资源上设置 [responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters) 属性。这可声明哪些方法响应参数将分派到客户端，哪些将从已从后端返回的集成响应参数或某些适用的正文属性进行映射。然后，您设置 [selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern)，以根据来自后端的响应来选择集成响应。对于非代理 HTTP 集成，这是一个正则表达式。例如，要将来自 HTTP 端点的所有 2xx HTTP 响应状态代码映射到此输出映射，请使用 `2\d{2}`。

**注意**  
API Gateway 使用 Java 模式的正则表达式来响应映射。有关更多信息，请参阅 Oracle 文档中的[模式](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)。

然后，作为集成响应设置的一部分，在相应的 [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源上设置 [responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#responseParameters) 属性，以指定参数到参数的映射。您还要设置 [responseTemplates](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#responseTemplates) 映射，以指定映射模板，为每个支持的内容类型设置一个映射模板。映射模板将集成响应参数或集成响应正文属性映射到方法响应正文。

 有关设置映射模板的更多信息，请参阅[针对 API Gateway 中 REST API 的数据转换](rest-api-data-transformations.md)。

# 在 API Gateway 中流式传输代理集成的集成响应
<a name="response-transfer-mode"></a>

您可以配置代理集成，以控制 API Gateway 如何返回您的集成响应。默认情况下，API Gateway 会等待收到完整的响应后再开始传输。但是，如果您将集成的响应传输模式设置为 `STREAM`，API Gateway 就不会等待响应完全生成完毕再发送给客户端。响应流式传输适用于所有 REST API 端点类型。

将响应流式传输用于以下使用案例：
+ 缩短生成式人工智能应用程序（如聊天机器人）的首字节时间（TTFB）。
+ 无需使用 S3 预签名 URL 即可流式传输大型图像、视频或音乐文件。
+ 执行长时间运行的操作时报告增量进度，如服务器发送事件（SSE）。
+ 超过 API Gateway 的 10 MB 响应有效载荷限制。
+ 无需申请增加集成超时限制即可突破 API Gateway 29 秒的超时限制。
+ 无需配置二进制媒体类型即可接收二进制有效载荷。

## 响应有效载荷流式传输的注意事项
<a name="response-transfer-mode-considerations"></a>

以下注意事项可能会影响您对响应有效载荷流式传输的使用：
+ 您只能对 `HTTP_PROXY` 或 `AWS_PROXY` 集成类型使用响应有效载荷流式传输。这包括 Lambda 代理集成和使用 `HTTP_PROXY` 集成的私有集成。
+ 默认传输模式设置为 `BUFFERED`。要使用响应流式传输，您必须将响应传输模式更改为 `STREAM`。
+ 仅 REST API 支持响应流式传输。
+ 不支持请求流式传输。
+ 响应流式传输的最长持续时间为 15 分钟。
+ 流受空闲超时限制。对于区域端点或私有端点，超时时间为 5 分钟。对于边缘优化型端点，超时时间为 30 秒。
+ 如果您对使用自有 CloudFront 分配的区域 REST API 启用响应流式传输，可以通过增加 CloudFront 分配的响应超时来实现超过 30 秒的空闲超时。有关更多信息，请参阅[响应超时](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesOrigin.html#DownloadDistValuesOriginResponseTimeout)。
+ 当响应传输模式设置为 `STREAM` 时，API Gateway 不支持需要缓冲整个集成响应的功能。因此，响应流式传输不支持以下功能：
  + 端点缓存
  + 内容编码。如果要压缩集成响应，请在集成中执行此操作。
  + 使用 VTL 的响应转换
+ 在每个流式响应中，前 10 MB 的响应有效载荷不受任何带宽限制。超过 10 MB 的响应有效载荷数据将限制为 2 MB/s。
+ 当客户端与 API Gateway 之间或 API Gateway 与 Lambda 之间的连接因超时而关闭时，Lambda 函数可能会继续执行。有关更多信息，请参阅[配置 Lambda 函数超时](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html)。
+ 响应流式传输会产生费用。有关更多信息，请参阅 [API Gateway 定价](https://aws.amazon.com/api-gateway/pricing/)。

# 在 API Gateway 中设置带有效载荷响应流式传输的 HTTP 代理集成
<a name="response-streaming-http"></a>

设置响应有效载荷流式传输时，您需要在方法的集成请求中指定响应传输模式。通过在集成请求中配置这些设置，可以控制 API Gateway 在集成响应之前和期间的行为。使用响应流式传输时，您可以将集成超时配置为最长 15 分钟。

当对 `HTTP_PROXY` 集成使用有效载荷响应流式传输时，API Gateway 必须完全接收所有标头后，才会发送 HTTP 响应状态码或任何 HTTP 响应标头。

## 创建带有效载荷响应流的 HTTP 代理集成
<a name="response-streaming-http-create"></a>

以下步骤展示了如何导入一个 `responseTransferMode` 设置为 `STREAM` 的新 API。如果您有现有的集成 API 并想要修改 `responseTransferMode`，请参阅[更新 HTTP 代理集成的响应传输模式](#response-streaming-http-update)。

------
#### [ AWS 管理控制台 ]

**创建带有效载荷响应流的 HTTP 代理集成**

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

1. 选择一个 REST API。

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

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

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

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

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

1. 对于**集成类型**，选择 **HTTP**。

1. 选择 **HTTP 代理集成**。

1. 对于**响应传输模式**，请选择**流式传输**。

1. 对于 **HTTP 方法**，请选择一种方法。

1. 对于**端点 URL**，请输入集成端点。确保选择能够产生大量有效载荷并流式返回给您的端点。

1. 选择**创建方法**。

创建方法后，部署您的 API。

**部署 API**

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

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

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

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

1. 选择**部署**。

------
#### [ AWS CLI ]

**创建带有效载荷响应流式传输的新 API**

1. 复制以下 Open API 文件，并将其保存为 `ResponseStreamDemoSwagger.yaml`。在此文件中，`responseTransferMode` 设置为 `STREAM`。集成端点设置为 `https://example.com`，但建议您将其修改为能生成大型有效载荷并流式返回给您的端点。

   ```
   openapi: "3.0.1"
   info:
     title: "ResponseStreamingDemo"
     version: "2025-04-28T17:28:25Z"
   servers:
   - url: "{basePath}"
     variables:
       basePath:
         default: "prod"
   paths:
     /streaming:
       get:
         x-amazon-apigateway-integration:
           httpMethod: "GET"
           uri: "https://example.com"
           type: "http_proxy"
           timeoutInMillis: 900000
           responseTransferMode: "STREAM"
   ```

1. 使用以下 `import-rest-api` 命令导入您的 OpenAPI 定义：

   ```
   aws apigateway import-rest-api \
     --body 'fileb://~/ResponseStreamDemoSwagger.yaml' \
     --parameters endpointConfigurationTypes=REGIONAL \
     --region us-west-1
   ```

1. 使用以下 `create-deployment` 命令将新 API 部署到某个阶段：

   ```
   aws apigateway create-deployment \
     --rest-api-id a1b2c3 \
     --stage-name prod \
     --region us-west-1
   ```

------

## 更新 HTTP 代理集成的响应传输模式
<a name="response-streaming-http-update"></a>

以下步骤展示了如何更新 HTTP 代理集成的响应传输模式。

------
#### [ AWS 管理控制台 ]

**更新 HTTP 代理集成的响应传输模式**

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

1. 选择一个 REST API。

1. 选择方法。

1. 在**集成请求**选项卡的**集成请求设置**下，选择**编辑**。

1. 对于**响应传输模式**，请选择**流式传输**。

1. 选择**保存**。

更新方法后，部署您的 API。

**部署 API**

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

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

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

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

1. 选择**部署**。

------
#### [ AWS CLI ]

以下 `update-integration` 命令将集成的传输模式从 `BUFFERED` 更新为 `STREAM`。对于所有现有 API，所有集成的响应传输模式均设置为 `BUFFERED`。

```
aws apigateway update-integration \
 --rest-api-id a1b2c3 \
 --resource-id aaa111 \
 --http-method GET \
 --patch-operations "op='replace',path='/responseTransferMode',value=STREAM" \
 --region us-west-1
```

您需要重新部署 API 才能使更改生效。如果您自定义了集成超时，该超时值将被移除，因为 API Gateway 将流式传输您的响应，最长持续时间为 5 分钟。

以下 `update-integration` 命令将集成的传输模式从 `STREAM` 更新为 `BUFFERED`：

```
aws apigateway update-integration \
 --rest-api-id a1b2c3 \
 --resource-id aaa111 \
 --http-method GET \
 --patch-operations "op='replace',path='/responseTransferMode',value=BUFFERED" \
 --region us-west-1
```

您需要重新部署 API 才能使更改生效。

------

# 在 API Gateway 中设置采用有效载荷响应流式传输的 Lambda 代理集成
<a name="response-transfer-mode-lambda"></a>

您可以流式传输 Lambda 函数的响应，以缩短首字节时间（TTFB），并在部分响应可用时立即将其发送给客户端。API Gateway 要求您使用 [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) Lambda API 来调用 Lambda 函数。API Gateway 会向 Lambda 函数传递一个事件对象。后端 Lambda 函数会对传入请求数据进行解析，以确定要返回的响应。为了让 API Gateway 能够流式传输 Lambda 输出，Lambda 函数必须按照 API Gateway 要求的[格式](#response-transfer-mode-lambda-format)输出。

## 流和缓冲响应传输模式下 Lambda 代理集成的差异
<a name="response-transfer-mode-lambda-comparison"></a>

以下列表描述了 Lambda 代理集成与用于响应流式传输的 Lambda 代理集成之间的差异：
+ API Gateway 使用 [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) API 调用用于响应流式处理的 Lambda 代理集成。这会生成不同的 URI，具体如下所示：

  ```
  arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations
  ```

  与 Lambda 代理集成相比，此 ARN 对 API 版本使用不同的日期和不同的服务操作。

  如果您使用 API Gateway 控制台进行响应流式传输，则控制台会自动为您使用正确的 URI。
+ 在 Lambda 代理集成中，API Gateway 仅在收到 Lambda 的完整响应后才会将响应发送给客户端。在用于响应流式传输的 Lambda 代理集成中，API Gateway 在收到 Lambda 的有效元数据和分隔符后即开始有效载荷流式传输。
+ 用于响应流式传输的 Lambda 代理集成使用与普通代理集成相同的输入格式，但要求不同的输出格式。

## 用于响应流式传输的 Lambda 代理集成格式
<a name="response-transfer-mode-lambda-format"></a>

当 API Gateway 调用具有响应流式传输功能的 Lambda 函数时，输入格式与代理集成的 Lambda 函数输入格式相同。有关更多信息，请参阅 [用于代理集成的 Lambda 函数的输入格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format)。

当 Lambda 向 API Gateway 流式传输响应时，响应必须遵循以下格式。该格式使用分隔符分隔元数据 JSON 和原始有效载荷。在这种情况下，有效载荷数据会按照流式 Lambda 函数传输的方式进行流式传输：

```
{
  "headers": {"headerName": "headerValue", ...},
  "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
  "cookies" : ["cookie1", "cookie2"],
  "statusCode": httpStatusCode
}<DELIMITER>PAYLOAD1 | PAYLOAD2 | PAYLOAD3
```

在输出中：
+ 如果不返回任何额外的响应标头，则可以不指定 `headers`、`multiValueHeaders`、`cookies` 和 `statusCode` 键。
+ `headers` 密钥只能包含单值标头。
+ 输出要求标头中包含 `Transfer-Encoding: chunked` 或 `Content-length: number`。如果您的函数未返回这两个标头中的任何一个，API Gateway 会在响应标头中添加 `Transfer-Encoding: chunked`。
+ `multiValueHeaders` 密钥可以包含多值标头以及单值标头。您可以使用 `multiValueHeaders` 密钥来指定所有额外的标头，包括任何单值标头。
+ 如果您指定 `headers` 和 `multiValueHeaders` 的值，API Gateway 会将它们合并为一个列表。如果两者都指定了相同的键/值对，则合并列表中只会出现 `multiValueHeaders` 的值。
+ 元数据必须是有效的 JSON 格式。仅支持 `headers`、`multiValueHeaders`、`cookies` 和 `statusCode` 键。
+ 必须在元数据 JSON 后面提供一个分隔符。该分隔符必须是 8 个空字节，且必须出现在流数据的前 16 KB 内。
+ API Gateway 对方法响应有效载荷没有特定格式要求。

如果您使用函数 URL 流式传输 Lambda 函数，必须修改 Lambda 函数的输入和输出以满足这些要求。

如果您的 Lambda 函数输出不符合此格式要求，API Gateway 仍可能调用您的 Lambda 函数，但会返回错误。下表展示了 API Gateway 支持的 API 集成请求设置与 Lambda 函数代码的组合。这包括响应传输模式为缓冲时支持的组合。


| 响应传输模式 | 函数代码符合要求的格式 | Lambda 调用 API | API Gateway 是否支持 | 
| --- | --- | --- | --- | 
|  流  |  是  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  可以。API Gateway 流式传输您的响应。  | 
|  流  |  否  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  否。API Gateway 调用您的 Lambda 函数并返回 500 错误响应。  | 
|  流  |  是  |   [调用](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  否。API Gateway 不支持此集成配置。  | 
|  流  |  否  |   [调用](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  否。API Gateway 不支持此集成配置。  | 
|  缓冲  |  是  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  否。API Gateway 不支持此集成配置。  | 
|  缓冲  |  否  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  否。API Gateway 不支持此集成配置。  | 
|  缓冲  |  是  |   [调用](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  API Gateway 返回 HTTP 标头和状态码，但不返回响应正文。  | 
|  缓冲  |  否  |   [调用](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  可以。这是 Lambda 代理集成。有关更多信息，请参阅 [Lambda 代理集成](set-up-lambda-proxy-integrations.md)。  | 

# 在 API Gateway 中配置采用有效载荷响应流式传输的 Lambda 代理集成
<a name="response-streaming-lambda-configure"></a>

在设置响应有效载荷流式传输时，您可以在资源的集成请求中指定传输模式。通过在集成请求中配置这些设置，可以控制 API Gateway 在集成响应之前和期间的行为。

## 用于响应流式传输的 Lambda 函数示例
<a name="response-streaming-lambda-example"></a>

您的 Lambda 函数必须遵循[用于响应流式传输的 Lambda 代理集成格式](response-transfer-mode-lambda.md#response-transfer-mode-lambda-format)。建议您使用三个示例 Lambda 函数之一来测试响应流式传输。创建 Lambda 函数时，请确保执行以下操作：
+ 为您的函数提供足够的超时时间。建议您将超时设置为至少 1 分钟，以了解响应流式传输。创建生产资源时，请确保您的 Lambda 函数超时涵盖整个请求周期。有关更多信息，请参阅[配置 Lambda 函数超时](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html)。
+ 使用最新的 Node.js 运行时。
+ 使用已提供 Lambda 响应流式传输的区域。

------
#### [ Using HttpResponseStream.from ]

以下代码示例通过 `awslambda.HttpResponseStream()` 方法（不使用 pipeline 方法）将 JSON 元数据对象和有效载荷流式传输回客户端，您无需创建分隔符。有关更多信息，请参阅[编写支持响应流式传输的 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/config-rs-write-functions.html)。

```
export const handler = awslambda.streamifyResponse(
  async (event, responseStream, context) => {
    const httpResponseMetadata = {
      "statusCode": 200,
      "headers": {
        "x-foo": "bar"
      },
      "multiValueHeaders": {
        "x-mv1": ["hello", "world"],
        "Set-Cookie": ["c1=blue", "c2=red"]
      }
    };

    responseStream = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata);
    await new Promise(r => setTimeout(r, 1000)); // synthetic delay

    responseStream.write("First payload ");
    await new Promise(r => setTimeout(r, 1000)); // synthetic delay

    responseStream.write("Final payload");
    responseStream.end();
});
```

------
#### [ Using the pipeline method ]

Lambda 建议，编写支持响应流式传输的函数时，使用 Node.js 原生运行时提供的 `awslambda.streamifyResponse()` 修饰器和 `pipeline()` 方法。使用 pipeline 方法时，您无需创建分隔符，Lambda 会自动处理。有关更多信息，请参阅[编写支持响应流式传输的 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/config-rs-write-functions.html)。

以下代码示例将 JSON 元数据对象和三个有效载荷流式传输回客户端。

```
import { pipeline } from 'node:stream/promises';
import { Readable } from 'node:stream';

export const handler = awslambda.streamifyResponse(
  async (event, responseStream, context) => {
    const httpResponseMetadata = {
      statusCode: 200,
      headers: {
        "Content-Type": "text/plain",
        "X-Custom-Header": "Example-Custom-Header"
      }
    };

    responseStream = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata);

    const dataStream = Readable.from(async function* () {
      yield "FIRST payload\n";
      await new Promise(r => setTimeout(r, 1000));
      yield "SECOND payload\n";
      await new Promise(r => setTimeout(r, 1000));
      yield "THIRD payload\n";
      await new Promise(r => setTimeout(r, 1000));
    }());

    await pipeline(dataStream, responseStream);
  }
);
```

------
#### [ Without using the pipeline method ]

以下代码示例在不使用 `awslambda.HttpResponseStream()` 方法的情况下，将 JSON 元数据对象和三个有效载荷流式传输回客户端。若未使用 `awslambda.HttpResponseStream()` 方法，您必须在元数据和有效载荷之间添加 8 个空字节的分隔符。

```
export const handler = awslambda.streamifyResponse(async (event, response, ctx) => {
  response.write('{"statusCode": 200, "headers": {"hdr-x": "val-x"}}');
  response.write("\x00".repeat(8)); // DELIMITER
  await new Promise(r => setTimeout(r, 1000));

  response.write("FIRST payload");
  await new Promise(r => setTimeout(r, 1000));

  response.write("SECOND payload");
  await new Promise(r => setTimeout(r, 1000));

  response.write("FINAL payload");
  response.end();
});
```

------

## 创建采用有效载荷响应流式传输的 Lambda 代理集成
<a name="response-streaming-lambda-create"></a>

以下步骤展示了如何创建采用有效载荷响应流式传输的 Lambda 代理集成。使用示例 Lambda 函数或创建自己的函数。

------
#### [ AWS 管理控制台 ]

**创建采用有效载荷响应流式传输的 Lambda 代理集成**

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

1. 选择一个 REST API。

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

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

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

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

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

1. 对于**集成类型**，选择 **Lambda**。

1. 选择 **Lambda 代理集成**。

1. 对于**响应传输模式**，请选择**流式传输**。

1. 对于 **Lambda 函数**，选择 Lambda 函数名称。

   API Gateway 控制台会自动使用 [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) API 来调用 Lambda 函数。您负责编写支持响应流式传输的 Lambda 函数。有关示例，请参阅[用于响应流式传输的 Lambda 函数示例](#response-streaming-lambda-example)。

1. 选择**创建方法**。

创建方法后，部署您的 API。

**部署 API**

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

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

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

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

1. 选择**部署**。

------
#### [ AWS CLI ]

以下步骤展示了如何导入一个 `responseTransferMode` 设置为 `STREAM` 的新 API。如果您有现有的集成 API 并想要修改 `responseTransferMode`，请参阅[更新 Lambda 代理集成的响应传输模式](#response-streaming-lambda-update)。

**创建带有效载荷响应流式传输的新 API**

1. 复制以下 Open API 文件，并将其保存为 `ResponseStreamDemoSwagger.yaml`。在此文件中，`responseTransferMode` 设置为 `STREAM`，集成 URI 设置为 `arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations`。

   将函数名 `my-function` 替换为支持响应流式传输的函数，并将凭证替换为具有允许 `apigateway` 服务调用 Lambda 函数的策略的 IAM 角色。

   ```
   openapi: "3.0.1"
   info:
     title: "ResponseStreamingDemo"
     version: "2025-04-28T17:28:25Z"
   servers:
   - url: "{basePath}"
     variables:
       basePath:
         default: "prod"
   paths:
     /lambda:
       get:
         x-amazon-apigateway-integration:
           httpMethod: "POST"
           uri: "arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations"
           type: "aws_proxy"
           timeoutInMillis: 90000
           responseTransferMode: "STREAM"
           credentials: "arn:aws:iam::111122223333:role/apigateway-lambda-role"
   ```

   您不用为凭证提供 IAM 角色，而是可以通过 Lambda 的 `add-permission` 命令添加基于资源的权限。

1. 使用以下 `import-rest-api` 命令导入您的 OpenAPI 定义：

   ```
   aws apigateway import-rest-api \
     --body 'fileb://~/ResponseStreamDemoSwagger.yaml' \
     --parameters endpointConfigurationTypes=REGIONAL \
     --region us-west-1
   ```

1. 使用以下 `create-deployment` 命令将新 API 部署到某个阶段：

   ```
   aws apigateway create-deployment \
     --rest-api-id a1b2c2 \
     --stage-name prod \
     --region us-west-1
   ```

------

### 更新 Lambda 代理集成的响应传输模式
<a name="response-streaming-lambda-update"></a>

以下步骤展示了如何更新 Lambda 代理集成的响应传输模式。当您将响应传输模式更改为流式传输时，请更新您的 Lambda 函数，使其符合响应流式传输的要求。使用示例 Lambda 函数或创建自己的函数。

------
#### [ AWS 管理控制台 ]

**更新 Lambda 代理集成的响应传输模式**

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

1. 选择一个 REST API。

1. 选择方法。

1. 在**集成请求**选项卡的**集成请求设置**下，选择**编辑**。

1. 对于**响应传输模式**，请选择**流式传输**。

1. 对于 **Lambda 函数**，选择 Lambda 函数名称。

1. 选择**保存**。

更新方法后，部署您的 API。

**部署 API**

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

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

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

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

1. 选择**部署**。

------
#### [ AWS CLI ]

1. 更新您的 Lambda 函数以支持流式传输。

1. 使用以下 AWS CLI 命令更新集成 URI 和集成的响应传输模式：

   ```
   aws apigateway update-integration \
    --rest-api-id a1b2c3 \
    --resource-id aaa111 \
    --http-method ANY \
    --patch-operations "[{\"op\":\"replace\",\"path\":\"/uri\",\"value\":\"arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations\"}, {\"op\":\"replace\",\"path\":\"/responseTransferMode\",\"value\":\"STREAM\"}]" \
    --region us-west-1
   ```

1. 重新部署 API 以使更改生效。

------

# 在 API Gateway 中排查响应流式传输问题
<a name="response-streaming-troubleshoot"></a>

以下故障排除指南可帮助解决使用响应流式传输的 API 问题。

## 一般故障排除
<a name="response-streaming-general-troubleshooting"></a>

您可以使用 [TestInvokeMethod](https://docs.aws.amazon.com/apigateway/latest/api/API_TestInvokeMethod.html) 或控制台的“测试”选项卡测试响应流式传输。使用测试调用功能进行响应流式传输时需注意以下事项：
+ 在测试方法时，API Gateway 会缓冲您的流式响应有效载荷。满足以下任一条件后，API Gateway 将返回包含缓冲的有效载荷的一次性响应：
  + 请求已完成
  + 已过去 35 秒
  + 已缓冲超过 1 MB 的响应有效载荷
+ 如果方法在 35 秒内未返回 HTTP 响应状态和所有标头，TestInvokeMethod 返回的响应状态为 0。
+ API Gateway 不会生成任何执行日志。

部署 API 后，可通过 curl 命令测试流式响应。建议使用 `-i` 选项在输出中包含协议响应标头。如需实时查看到达的响应数据，使用 curl 选项 `--no-buffer`。

## 排查 curl 错误
<a name="response-streaming-troubleshoot-curl-error"></a>

如果测试集成时出现 `curl: (18) transfer closed with outstanding read data remaining` 错误，需确保集成超时时间足够长。如果您使用的是 Lambda 函数，则需要更新 Lambda 函数的响应超时。有关更多信息，请参阅[配置 Lambda 函数超时](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html)。

## 通过访问日志排查问题
<a name="response-streaming-troubleshoot-access-logging"></a>

可通过 REST API 阶段的访问日志记录并排查响应流问题。除现有变量外，还可使用以下访问日志变量：

`$context.integration.responseTransferMode`  
您的集成的响应传输模式。此值可以是 `BUFFERED` 或 `STREAMED`。

`$context.integration.timeToAllHeaders`  
从 API Gateway 建立集成连接到从客户端接收所有集成响应头之间的时间间隔。

`$context.integration.timeToFirstContent`  
API Gateway 建立集成连接到接收第一个内容字节之间的时间间隔。

`$context.integration.latency` 或 `$context.integrationLatency`  
从 API Gateway 建立集成连接到集成响应流完成之间间隔的时间。

下图展示了这些访问日志变量如何表示响应流的不同组成部分。

![\[API Gateway 中响应流的访问日志变量\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/response-streaming-figure.png)


有关访问日志的更多信息，请参阅 [为 API Gateway 中的 REST API 设置 CloudWatch 日志记录](set-up-logging.md)。您也可以使用 X-Ray 来监控您的响应流。有关更多信息，请参阅 [在 API Gateway 中使用 X-Ray 跟踪用户对 REST API 的请求](apigateway-xray.md)。

# 针对 API Gateway 中的 REST API 的私有集成
<a name="private-integration"></a>

通过私有集成，可将 Amazon VPC 内的 HTTP/HTTPS 资源暴露给 VPC 外的客户端访问。这会将对私有 VPC 资源的访问扩展到 VPC 边界之外。您可以使用 API Gateway 支持的任何[授权方法](apigateway-control-access-to-api.md)来控制对 API 的访问。

要创建私有集成，您必须首先创建 VPC 链接。API Gateway 支持用于 REST API 的 VPC 链接 V2。VPC 链接 V2 允许您创建私有集成，无需使用网络负载均衡器即可将 REST API 连接到应用程序负载均衡器。使用应用程序负载均衡器可以连接到 Amazon ECS 基于容器的应用程序和许多其他后端。VPC 链接 V1 被视为传统集成类型。虽然 API Gateway 支持这些类型，但建议您不要创建新的 VPC 链接 V1。

## 注意事项
<a name="private-integrations-considerations"></a>

以下注意事项可能会影响您对私有集成的使用：
+ 所有资源必须由同一 AWS 账户拥有。这包括负载均衡器、VPC 链接和 REST API。
+ 默认情况下，私有集成流量使用 HTTP 协议。要使用 HTTPS，请指定包含安全服务器名称的 [https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri](https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri)，例如 `https://example.com:443/test`。
+ 在私有集成中，API Gateway 会在发送给后端资源的请求中包括 API 端点的[阶段](set-up-stages.md)部分。例如，若请求 API 的 `test` 阶段，API Gateway 会在发送给私有集成的请求中包含 `test/path`。如需从发送给后端资源的请求中移除阶段名称，可通过[参数映射](rest-api-parameter-mapping.md)覆盖 `$context.requestOverride.path` 变量。
+ 不支持与 AWS Cloud Map 的私有集成。

**Topics**
+ [注意事项](#private-integrations-considerations)
+ [在 API Gateway 中设置 VPC 链接 V2](apigateway-vpc-links-v2.md)
+ [设置私有集成](set-up-private-integration.md)
+ [使用 VPC 链接 V1 的私有集成（旧版）](vpc-links-v1.md)

# 在 API Gateway 中设置 VPC 链接 V2
<a name="apigateway-vpc-links-v2"></a>

通过 VPC 链接，您可以创建私有集成，将 API 路由连接到 VPC 中的私有资源，例如应用程序负载均衡器或基于 Amazon ECS 容器的应用程序。私有集成使用 VPC 链接 V2 来封装 API Gateway 与目标 VPC 资源之间的连接。您可以跨不同的资源和 API 重用 VPC 链接。

创建 VPC 链接时，API Gateway 在您的账户中为 VPC 链接 V2 创建和管理[弹性网络接口](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html)。此过程可能耗时数分钟。当 VPC 链接 V2 可供使用时，其状态将从 `PENDING` 转换为 `AVAILABLE`。

**注意**  
如果 60 天内未通过 VPC 链接发送任何流量，其状态会变为 `INACTIVE`。当 VPC 链接处于 `INACTIVE` 状态时，API Gateway 删除 VPC 链接的所有网络接口。这会导致依赖于 VPC 链接的 API 请求失败。如果 API 请求恢复，API Gateway 将重新预置网络接口。创建网络接口和重新激活 VPC 链接可能需要几分钟时间。您可以使用 VPC 链接状态来监控 VPC 链接的状态。

## 使用 AWS CLI 创建 VPC 链接 V2
<a name="apigateway-vpc-links-v2-create"></a>

要创建 VPC 链接 V2，涉及的所有资源必须由同一 AWS 账户拥有。使用以下 [create-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-vpc-link.html) 命令创建 VPC 链接：

```
aws apigatewayv2 create-vpc-link --name MyVpcLink \
    --subnet-ids subnet-aaaa subnet-bbbb \
    --security-group-ids sg1234 sg5678
```

**注意**  
VPC 链接 V2 是不可变的。创建 VPC 链接 V2 后，您无法更改其子网或安全组。

## 使用 AWS CLI 删除 VPC 链接 V2
<a name="apigateway-vpc-links-v2-delete"></a>

使用以下 [delete-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/delete-vpc-link.html) 命令删除 VPC 链接。

```
aws apigatewayv2 delete-vpc-link --vpc-link-id abcd123
```

## 按区域的可用性
<a name="apigateway-vpc-links-v2-availability"></a>

以下区域和可用区支持 VPC 链接 V2：

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/apigateway-vpc-links-v2.html)

# 设置私有集成
<a name="set-up-private-integration"></a>

要创建与应用程序负载均衡器或网络负载均衡器的私有集成，请创建 HTTP 代理集成，指定要使用的 [VPC 链接 V2](apigateway-vpc-links-v2.md)，并提供网络负载均衡器或应用程序负载均衡器的 ARN。默认情况下，私有集成流量使用 HTTP 协议。要使用 HTTPS，请指定包含安全服务器名称的 [https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri](https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri)，例如 `https://example.com:443/test`。有关如何创建使用私有集成的 REST API 的完整教程，请参阅[教程：利用私有集成创建 REST API](getting-started-with-private-integration.md)。

## 创建私有集成
<a name="set-up-private-integration-create"></a>

以下步骤介绍如何创建私有集成，该私有集成通过 VPC 链接 V2 连接到负载均衡器。

------
#### [ AWS 管理控制台 ]

有关如何创建私有集成的教程，请参阅[教程：利用私有集成创建 REST API](getting-started-with-private-integration.md)。

------
#### [ AWS CLI ]

以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/latest/api/API_PutIntegration.html) 命令创建私有集成，该集成通过 VPC 链接 V2 连接到负载均衡器：

```
aws apigateway put-integration \
    --rest-api-id abcdef123 \
    --resource-id aaa000 \
    --integration-target 'arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011' \
    --uri 'https://example.com:443/path' \
    --http-method GET \
    --type HTTP_PROXY \
    --integration-http-method GET \
    --connection-type VPC_LINK \
    --connection-id bbb111
```

您可以改用阶段变量，而不是直接提供连接 ID。将 API 部署到阶段时，您要设置 VPC 链接 V2 ID。以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/latest/api/API_PutIntegration.html) 命令对 VPC 链接 V2 ID 使用阶段变量来创建私有集成：

```
aws apigateway put-integration \
    --rest-api-id abcdef123 \
    --resource-id aaa000 \
    --integration-target 'arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011' \
    --uri 'https://example.com:443/path' \
    --http-method GET \
    --type HTTP_PROXY \
    --integration-http-method GET \
    --connection-type VPC_LINK \
    --connection-id "\${stageVariables.vpcLinkV2Id}"
```

确保使用双引号括起阶段变量表达式（\$1\$1stageVariables.vpcLinkV2Id\$1）并转义 \$1 字符。

------
#### [ OpenAPI ]

您可以通过导入 API 的 OpenAPI 文件，设置具有私有集成的 API。其设置类似于具有 HTTP 集成的 API 的 OpenAPI 定义，但有以下例外：
+ 您必须明确将 `connectionType` 设置为 `VPC_LINK`。
+ 您必须明确将 `connectionId` 设置为 `VpcLinkV2` 的 ID 或者设置为引用 `VpcLinkV2` 的 ID 的阶段变量。
+ 私有集成中的 `uri` 参数指向 VPC 中的 HTTP/HTTPS 端点，但是用于设置集成请求的 `Host` 标头。
+ 在 VPC 中，使用具有 HTTPS 端点的私有集成中的 `uri` 参数，根据在 VPC 端点上已安装证书中的名称验证所述域名。

 您可以使用阶段变量来引用 `VpcLinkV2` ID。或者，您可以将 ID 值直接分配到 `connectionId`。

以下 JSON 格式的 OpenAPI 文件显示的示例中，API 具有 VPC 链接，通过阶段变量 (`${stageVariables.vpcLinkIdV2}`) 来引用：

```
{
  "swagger": "2.0",
  "info": {
    "version": "2017-11-17T04:40:23Z",
    "title": "MyApiWithVpcLinkV2"
  },
  "host": "abcdef123.execute-api.us-west-2.amazonaws.com",
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/": {
      "get": {
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "uri": "https://example.com:443/path",
          "passthroughBehavior": "when_no_match",
          "connectionType": "VPC_LINK",
          "connectionId": "${stageVariables.vpcLinkV2Id}",
          "integration-target": "arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011",
          "httpMethod": "GET",
          "type": "http_proxy"
        }
      }
    }
  },
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

------

## 更新私有集成
<a name="set-up-private-integration-update"></a>

以下示例更新私有集成的 VPC 链接 V2。

------
#### [ AWS 管理控制台 ]

**更新私有集成**

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

1. 选择使用私有集成的 REST API。

1. 选择使用私有集成的资源和方法。

1. 在**集成请求**选项卡的**集成请求设置**下，选择**编辑**。

1. 您可以编辑私有集成的设置。如果您当前使用的是 VPC 链接 V1，则可以将您的 VPC 链接更改为 VPC 链接 V2。

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

------
#### [ AWS CLI ]

以下 [update-integration](https://docs.aws.amazon.com/cli/latest/reference/latest/api/API_PutIntegration.html) 命令将私有集成更新为使用 VPC 链接 V2：

```
aws apigateway update-integration \
    --rest-api-id a1b2c3d4e5 \
    --resource-id a1b2c3 \
    --http-method GET \
    --patch-operations "[{\"op\":\"replace\",\"path\":\"/connectionId\",\"value\":\"pk0000\"}, {\"op\":\"replace\",\"path\":\"/uri\",\"value\":\"http://example.com\"}, {\"op\":\"replace\",\"path\":\"/integrationTarget\",\"value\":\"arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011\"}]"
```

------

# 使用 VPC 链接 V1 的私有集成（旧版）
<a name="vpc-links-v1"></a>

**注意**  
以下私有集成实现使用 VPC 链接 V1。VPC 链接 V1 是旧版资源。建议您将 [VPC 链接 V2 用于 REST API](apigateway-vpc-links-v2.md)。

要创建私有集成，您必须首先创建网络负载均衡器。您的网络负载均衡器必须具有可将请求路由到 VPC 中的资源的[侦听器](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-listeners.html)。要提高 API 的可用性，请确保网络负载均衡器将流量路由到 AWS 区域 中多个可用性区域中的资源。然后，您创建一个 VPC 链接，来连接 API 和网络负载均衡器。创建 VPC 链接后，您可以创建私有集成，从而通过 VPC 链接和网络负载均衡器将流量从 API 路由到 VPC 中的资源。网络负载均衡器和 API 必须归同一个 AWS 账户所有。

**Topics**
+ [为 API Gateway 私有集成设置网络负载均衡器（旧版）](set-up-nlb-for-vpclink-using-console.md)
+ [授予 API Gateway 创建 VPC 链接的权限（旧版）](grant-permissions-to-create-vpclink.md)
+ [使用 AWS CLI 设置具有私有集成的 API Gateway API（旧版）](set-up-api-with-vpclink-cli.md)
+ [用于私有集成的 API Gateway 账户（旧版）](set-up-api-with-vpclink-accounts.md)

# 为 API Gateway 私有集成设置网络负载均衡器（旧版）
<a name="set-up-nlb-for-vpclink-using-console"></a>

**注意**  
以下私有集成实现使用 VPC 链接 V1。VPC 链接 V1 是旧版资源。建议您将 [VPC 链接 V2 用于 REST API](apigateway-vpc-links-v2.md)。

 以下过程概述使用 Amazon EC2 控制台为 API Gateway 私有集成设置网络负载均衡器 (NLB) 的步骤，并提供对各个步骤的详细说明的参考。

对于其中包含有您的资源的每个 VPC，您只需要配置一个 NLB 和一个 VPCLink。NLB 支持每个 NLB 有多个[侦听器](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-listeners.html)和[目标组](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html)。您可以在 NLB 上将每个服务配置成为一个特定的侦听器，然后使用一个 VPCLink 连接到 NLB。在 API Gateway 中创建私有集成时，您随后可以定义每个服务使用已为各个服务分配的特定端口。有关更多信息，请参阅 [教程：利用私有集成创建 REST API](getting-started-with-private-integration.md)。网络负载均衡器和 API 必须归同一个 AWS 账户所有。

**使用 API Gateway 控制台为私有集成创建网络负载均衡器**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在 Amazon EC2 实例上设置 Web 服务器。如需示例设置，请参阅[在 Amazon Linux 2 上安装 LAMP Web 服务器](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-lamp-amazon-linux-2.html)。

1. 创建网络负载均衡器，将 EC2 实例注册到目标组，然后将目标组添加到网络负载均衡器的侦听器。有关详细信息，请参阅[网络负载均衡器入门](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancer-getting-started.html)中的说明。

1. 创建网络负载均衡器之后，执行以下操作：

   1.  记录网络负载均衡器的 ARN。您需要它在 API Gateway 中创建 VPC 链接，用于将 API 与位于网络负载均衡器之后的 VPC 资源集成。

   1.  关闭 PrivateLink 的安全组评估。
      + 要使用控制台关闭对 PrivateLink 流量的安全组评估，可以选择**安全**选项卡，然后选择**编辑**。在**安全设置**下，清除**对 PrivateLink 流量强制执行入站规则**。
      + 要关闭对 PrivateLink 流量的安全组评估，请使用以下 [set-security-groups](https://docs.aws.amazon.com/cli/latest/reference/elbv2/set-security-groups.html) 命令：

        ```
        aws elbv2 set-security-groups --load-balancer-arn arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/net/my-loadbalancer/abc12345 \
          --security-groups sg-123345a --enforce-security-group-inbound-rules-on-private-link-traffic off
        ```

**注意**  
请勿向 API Gateway CIDR 添加任何依赖项，因为这些依赖项必然会未经通知而更改。

# 授予 API Gateway 创建 VPC 链接的权限（旧版）
<a name="grant-permissions-to-create-vpclink"></a>

**注意**  
以下私有集成实现使用 VPC 链接 V1。VPC 链接 V1 是旧版资源。建议您将 [VPC 链接 V2 用于 REST API](apigateway-vpc-links-v2.md)。

对于您或者您账户中的用户，如果要创建和维护 VPC 链接，您或者用户必须有权创建、删除和查看 VPC 端点服务配置，更改 VPC 端点服务权限，以及检查负载均衡器。要授予此类权限，请使用以下步骤。

**授予创建、更新和删除 VPC 链接的权限**

1. 创建类似于以下的 IAM 策略：

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "apigateway:POST",
                   "apigateway:GET",
                   "apigateway:PATCH",
                   "apigateway:DELETE"
               ],
               "Resource": [
                   "arn:aws:apigateway:us-east-1::/vpclinks",
                   "arn:aws:apigateway:us-east-1::/vpclinks/*"
               ]
           },
           {
               "Effect": "Allow",
               "Action": [
                   "elasticloadbalancing:DescribeLoadBalancers"
               ],
               "Resource": "*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "ec2:CreateVpcEndpointServiceConfiguration",
                   "ec2:DeleteVpcEndpointServiceConfigurations",
                   "ec2:DescribeVpcEndpointServiceConfigurations",
                   "ec2:ModifyVpcEndpointServicePermissions"
               ],
               "Resource": "*"
           }
       ]
   }
   ```

------

   如果您要为 VPC 链接启用标记，请确保允许标记操作。有关更多信息，请参阅 [允许标记操作](apigateway-tagging-iam-policy.md#allow-tagging)。

1. 创建或选择 IAM 角色并将前述策略附加到角色。

1. 将 IAM 角色分配给您或您账户中创建 VPC 链接的用户。

# 使用 AWS CLI 设置具有私有集成的 API Gateway API（旧版）
<a name="set-up-api-with-vpclink-cli"></a>

**注意**  
以下私有集成实现使用 VPC 链接 V1。VPC 链接 V1 是旧版资源。建议您将 [VPC 链接 V2 用于 REST API](apigateway-vpc-links-v2.md)。

以下教程演示了如何使用 AWS CLI 创建 VPC 链接和私有集成。需要满足以下先决条件：
+ 您需要创建并配置了一个以 VPC 源为目标的网络负载均衡器。有关更多信息，请参阅 [为 API Gateway 私有集成设置网络负载均衡器（旧版）](set-up-nlb-for-vpclink-using-console.md)。这必须与您的 API 位于同一个 AWS 账户中。您需要网络负载均衡器 ARN 来创建 VPC 链接。
+ 要创建和管理 `VpcLink`，您必须具有在 API 中创建 `VpcLink` 的权限。您不需要具有使用 `VpcLink` 的权限。有关更多信息，请参阅 [授予 API Gateway 创建 VPC 链接的权限（旧版）](grant-permissions-to-create-vpclink.md)。

**使用 AWS CLI 设置具有私有集成的 API**

1. 使用以下 [create-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-vpc-link.html) 命令创建以指定的网络负载均衡器作为目标的 `VpcLink`：

   ```
   aws apigateway create-vpc-link \
       --name my-test-vpc-link \
       --target-arns arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/net/my-vpclink-test-nlb/1234567890abcdef
   ```

   此命令的输出确认收到请求并显示正在创建的 `VpcLink` 的 `PENDING` 状态。

   ```
   {
       "status": "PENDING", 
       "targetArns": [
           "arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/net/my-vpclink-test-nlb/1234567890abcdef"
       ], 
       "id": "gim7c3", 
       "name": "my-test-vpc-link"
   }
   ```

   API Gateway 需要 2-4 分钟才能完成创建 `VpcLink`。操作成功完成后，`status` 为 `AVAILABLE`。您可以通过调用以下 [get-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-vpc-link.html) 命令来验证这一点：

   ```
   aws apigateway get-vpc-link --vpc-link-id gim7c3
   ```

   如果操作失败，您将收到 `FAILED` 状态，以及包含错误消息的 `statusMessage`。例如，如果您尝试使用已经与 VPC 端点关联的网络负载均衡器创建 `VpcLink`，在 `statusMessage` 属性上将获得以下内容：

   ```
   "NLB is already associated with another VPC Endpoint Service"
   ```

   在成功创建 `VpcLink` 之后，您可以创建 API 并通过 `VpcLink` 将其与 VPC 资源集成。

   记下新创建的 `VpcLink` 的 `id` 值。在此示例输出中，它是 `gim7c3`。设置私有集成时需要该值。

1. 使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建 API Gateway [https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源：

   ```
   aws apigateway create-rest-api --name 'My VPC Link Test'
   ```

   请记录返回结果中 `RestApi` 的 `id` 值和 `RestApi` 的 `rootResourceId` 值。您需要该值才能在 API 上进一步执行操作。

   接下来，我们将在根资源（`/`）上创建仅具有 `GET` 方法的 API，并将方法与 `VpcLink` 集成。

1. 使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建 `GET /` 方法：

   ```
   aws apigateway put-method \
          --rest-api-id  abcdef123 \
          --resource-id skpp60rab7 \
          --http-method GET \
          --authorization-type "NONE"
   ```

   如果您不将代理集成用于 `VpcLink`，则还必须至少设置 `200` 状态代码的一个方法响应。您在这里使用代理集成。

1. 创建 `GET /` 方法后，即可设置集成。对于私有集成，请使用 `connection-id` 参数来提供 `VpcLink` ID。您可以使用阶段变量或直接输入 `VpcLink` ID。`uri` 参数不用于将请求路由到端点，而是用于设置 `Host` 标头和证书验证。

------
#### [ Use the VPC link ID ]

   使用以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 命令，在集成中直接使用 `VpcLink` ID：

   ```
   aws apigateway put-integration \
       --rest-api-id abcdef123 \
       --resource-id skpp60rab7 \
       --uri 'http://my-vpclink-test-nlb-1234567890abcdef.us-east-2.amazonaws.com' \
       --http-method GET \
       --type HTTP_PROXY \
       --integration-http-method GET \
       --connection-type VPC_LINK \
       --connection-id gim7c3
   ```

------
#### [ Use a stage variable ]

   使用以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 命令，来使用阶段变量引用 VPC 链接 ID。将 API 部署到阶段时，您要设置 VPC 链接 ID。

   ```
   aws apigateway put-integration \
       --rest-api-id abcdef123 \
       --resource-id skpp60rab7 \
       --uri 'http://my-vpclink-test-nlb-1234567890abcdef.us-east-2.amazonaws.com' \
       --http-method GET \
       --type HTTP_PROXY \
       --integration-http-method GET \
       --connection-type VPC_LINK \
       --connection-id "\${stageVariables.vpcLinkId}"
   ```

   请确保使用双引号括起阶段变量表达式 (`${stageVariables.vpcLinkId}`) 并转义 `$` 字符。

------

   也可以随时更新集成来更改 `connection-id`。使用以下 [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration.html) 命令更新集成：

   ```
    aws apigateway update-integration \
       --rest-api-id abcdef123 \
       --resource-id skpp60rab7 \
       --http-method GET \
       --patch-operations '[{"op":"replace","path":"/connectionId","value":"${stageVariables.vpcLinkId}"}]'
   ```

   请确保使用字符串化的 JSON 列表作为 `patch-operations` 参数值。

   由于您使用了私有代理集成，因此 API 现已准备好，可用于部署和测试运行。

1. 如果您使用了阶段变量来定义 `connection-id`，则需要部署 API 来对其进行测试。使用以下 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 命令，部署具有阶段变量的 API：

   ```
   aws apigateway create-deployment \
       --rest-api-id abcdef123 \
       --stage-name test \
       --variables vpcLinkId=gim7c3
   ```

   要使用不同 `VpcLink` ID（例如 `asf9d7`）更新阶段变量，请使用以下 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) 命令：

   ```
   aws apigateway update-stage \
       --rest-api-id abcdef123 \
       --stage-name test \
       --patch-operations op=replace,path='/variables/vpcLinkId',value='asf9d7'
   ```

   使用 `VpcLink` ID 文本对 `connection-id` 属性进行硬编码时，无需部署 API 来对其进行测试。在部署 API 之前，使用 [test-invoke-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/test-invoke-method.html) 命令对其进行测试。

1. 使用以下命令来调用 API：

   ```
   curl -X GET https://abcdef123.execute-api.us-east-2.amazonaws.com/test
   ```

   此外，您可以在 Web 浏览器中输入 API 的调用 URL 来查看结果。

# 用于私有集成的 API Gateway 账户（旧版）
<a name="set-up-api-with-vpclink-accounts"></a>

在创建 `VpcLink` 时，以下特定于区域的 API Gateway 账户 ID 会作为 `AllowedPrincipals` 自动添加到 VPC 端点服务中。


| **区域** | **账户 ID** | 
| --- | --- | 
| us-east-1 | 392220576650 | 
| us-east-2 | 718770453195 | 
| us-west-1 | 968246515281 | 
| us-west-2 | 109351309407 | 
| ca-central-1 | 796887884028 | 
| eu-west-1 | 631144002099 | 
| eu-west-2 | 544388816663 | 
| eu-west-3 | 061510835048 | 
| eu-central-1 | 474240146802 | 
| eu-central-2 | 166639821150 | 
| eu-north-1 | 394634713161 | 
| eu-south-1 | 753362059629 | 
| eu-south-2 | 359345898052 | 
| ap-northeast-1 | 969236854626 | 
| ap-northeast-2 | 020402002396 | 
| ap-northeast-3 | 360671645888 | 
| ap-southeast-1 | 195145609632 | 
| ap-southeast-2 | 798376113853 | 
| ap-southeast-3 | 652364314486 | 
| ap-southeast-4 | 849137399833 | 
| ap-south-1 | 507069717855 | 
| ap-south-2 | 644042651268 | 
| ap-east-1 | 174803364771 | 
| sa-east-1 | 287228555773 | 
| me-south-1 | 855739686837 | 
| me-central-1 | 614065512851 | 

# 针对 API Gateway 中的 REST API 的模拟集成
<a name="how-to-mock-integration"></a>

Amazon API Gateway 支持 API 方法的模拟集成。借助该特征，API 开发人员可以直接从 API Gateway 生成 API 响应，无需集成后端。作为 API 开发人员，您可以在项目开发结束之前使用此特征，以便不妨碍需要使用 API 开展工作的相关团队。您还可以使用此特征来预配置 API 的登录页面，该网页可提供您的 API 概述和导航。有关此类登录页面的示例，请参阅 中所述示例 API 的根资源上 GET 方法的集成请求和响应[教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)

作为 API 开发人员，您可以决定 API Gateway 响应模拟集成的方式。为此，您可以配置方法的集成请求和集成响应，以将响应与给定的状态代码相关联。对于具有模拟集成以返回 `200` 响应的方法，请配置集成请求正文映射模板以返回下列内容。

```
{"statusCode": 200}
```

配置 `200` 集成响应以具有以下正文映射模板，例如：

```
{
    "statusCode": 200,
    "message": "Go ahead without me."
}
```

 与此类似，举例而言，对于返回 `500` 错误响应的方法，请设置集成请求正文映射模板以返回下列内容。

```
{"statusCode": 500}
```

例如，使用以下映射模板设置 `500` 集成响应：

```
{
    "statusCode": 500,
    "message": "The invoked method is not supported on the API resource."
}
```

或者，您可以让模拟集成的方法返回默认集成响应，无需定义集成请求映射模板。默认集成响应是具有未定义 **HTTP status regex (HTTP 状态正则表达式)** 的响应。请确保设置了合适的传递行为。

**注意**  
模拟集成并非用于支持大型响应模板。如果您的使用案例需要它们，您应该考虑改为使用 Lambda 集成。

使用集成请求映射模板，您可以注入应用程序逻辑，用来确定基于特定条件返回什么模拟集成响应。例如，您可以在传入请求上使用 `scope` 查询参数来确定返回成功响应还是错误响应：

```
{
  #if( $input.params('scope') == "internal" )
    "statusCode": 200
  #else
    "statusCode": 500
  #end
}
```

这样，模拟集成的方法让内部调用通过，同时拒绝其他类型的调用并提供错误响应。



本部分介绍如何使用 API Gateway 控制台来启用 API 方法模拟集成。

**Topics**
+ [使用 API Gateway 控制台启用模拟集成](how-to-mock-integration-console.md)

# 使用 API Gateway 控制台启用模拟集成
<a name="how-to-mock-integration-console"></a>

您必须在 API Gateway 中有一个可用的方法。按照[教程：使用 HTTP 非代理集成创建 REST API](api-gateway-create-api-step-by-step.md)中的说明进行操作。

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

   要创建方法，请执行以下操作：

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

   1. 对于**集成类型**，选择**模拟**。

   1. 选择**创建方法**。

   1. 在**方法请求**选项卡上，对于**方法请求设置**，选择**编辑**。

   1. 选择 **URL 查询字符串参数**。选择**添加查询字符串**，然后为**名称**中输入 **scope**。此查询参数确定调用方是否为内部。

   1. 选择**保存**。

1. 在**方法响应**选项卡上，选择**创建响应**，然后执行以下操作：

   1. 对于 **HTTP 状态**，输入 **500**。

   1. 选择**保存**。

1. 在**集成请求**选项卡上，对于**集成请求设置**，选择**编辑**。

1. 选择**映射模板**，然后执行以下操作：

   1. 选择**添加映射模板**。

   1. 对于**内容类型**，输入 **application/json**。

   1. 对于**模板正文**，输入以下内容：

      ```
      {
        #if( $input.params('scope') == "internal" )
          "statusCode": 200
        #else
          "statusCode": 500
        #end
      }
      ```

   1. 选择**保存**。

1. 在**集成响应**选项卡上，对于**默认 - 响应**，选择**编辑**。

1. 选择**映射模板**，然后执行以下操作：

   1. 对于**内容类型**，输入 **application/json**。

   1. 对于**模板正文**，输入以下内容：

      ```
      {
          "statusCode": 200,
          "message": "Go ahead without me"
      }
      ```

   1. 选择**保存**。

1. 选择**创建响应**。

   要创建 500 响应，请执行以下操作：

   1. 对于 **HTTP 状态正则表达式**，输入 **5\$1d\$12\$1**。

   1. 对于**方法响应状态**，选择 **500**。

   1. 选择**保存**。

   1. 对于 **5\$1d\$12\$1 - 响应**，选择**编辑**。

   1. 选择**映射模板**，然后选择**添加映射模板**。

   1. 对于**内容类型**，输入 **application/json**。

   1. 对于**模板正文**，输入以下内容：

      ```
      {
          "statusCode": 500,
          "message": "The invoked method is not supported on the API resource."
      }
      ```

   1. 选择**保存**。

1.  选择**测试**选项卡。您可能需要选择右箭头按钮，以显示该选项卡。要测试模拟集成，请执行以下操作：

   1. 在**查询字符串**下，输入 `scope=internal`。选择 **Test (测试)**。测试结果显示：

      ```
      Request: /?scope=internal
      Status: 200
      Latency: 26 ms
      Response Body
      
      {
        "statusCode": 200,
        "message": "Go ahead without me"
      }
      
      Response Headers
      
      {"Content-Type":"application/json"}
      ```

   1. 在 `scope=public` 下输入 `Query strings` 或将其留空。选择 **Test (测试)**。测试结果显示：

      ```
      Request: /
      Status: 500
      Latency: 16 ms
      Response Body
      
      {
        "statusCode": 500,
        "message": "The invoked method is not supported on the API resource."
      }
      
      Response Headers
      
      {"Content-Type":"application/json"}
      ```

您也可以首先将标头添加到方法响应，然后在集成响应中设置标头映射，从而在模拟集成响应中返回标头。实际上，这是 API Gateway 控制台通过返回 CORS 需要的标头来启用 CORS 支持的方法。

# 针对 API Gateway 中的 REST API 的请求验证
<a name="api-gateway-method-request-validation"></a>

 您可以配置 API Gateway，使其在处理集成请求之前对 API 请求执行基本验证。如果验证失败，API Gateway 会立即取消请求、向调用方返回 400 错误响应，并在 CloudWatch Logs 中发布验证结果。这可以减少对后端进行的不必要调用。更重要的是，它可以让您把精力集中在特定于应用程序的验证工作上。您可以通过验证所需请求参数是否有效并且不为空，或为更复杂的数据验证指定一个模型架构，从而验证请求正文。

**Topics**
+ [API Gateway 中的基本请求验证概览](#api-gateway-request-validation-basic-definitions)
+ [针对 REST API 的数据模型](models-mappings-models.md)
+ [在 API Gateway 中设置基本请求验证](api-gateway-request-validation-set-up.md)
+ [AWS CloudFormation 模板，提供带有基本请求验证的示例 API](api-gateway-request-validation-sample-cloudformation.md)

## API Gateway 中的基本请求验证概览
<a name="api-gateway-request-validation-basic-definitions"></a>

 API Gateway 可以执行基本请求验证，以便您可以专注于后端的应用程序特定验证。进行验证时，API Gateway 验证以下一项或两项条件：
+ 传入请求的 URI、查询字符串和标头中带有所需的请求参数且都不为空。API Gateway 仅检查参数是否存在，而不检查类型或格式。
+  适用的请求有效载荷遵循对应于给定内容类型的方法的已配置 [JSON schema](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) 请求。如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请将数据模型的内容类型设置为 `$default`。

要开启验证，您需要在[请求验证程序](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html)中指定验证规则，将验证程序添加到 API 的[请求验证程序的映射](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html)中，并将验证程序分配给各个 API 方法。

**注意**  
请求正文验证和[API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)是两个独立的主题。当请求负载没有匹配的模型架构时，可以选择传递或阻止原始负载。有关更多信息，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

# 针对 REST API 的数据模型
<a name="models-mappings-models"></a>

在 API Gateway 中，模型定义负载的数据结构。在 API Gateway 中，使用 [JSON 架构草案 4](https://tools.ietf.org/html/draft-zyp-json-schema-04) 定义模型。以下 JSON 对象是 Pet Store 示例中的示例数据。

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

数据包含宠物的 `id`、`type` 和 `price`。这些数据的模型允许您：
+ 使用基本请求验证。
+ 创建用于数据转换的映射模板。
+ 生成 SDK 时创建用户定义的数据类型（UDT）。

![\[PetStore API 的示例 JSON 数据模型。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/how-to-validate-requests.png)


在这个模型中：

1. `$schema` 对象表示一个有效的 JSON 架构版本标识符。此架构为 JSON 架构草案 v4。

1. `title` 对象是人类可读的模型标识符。此标题是 `PetStoreModel`。

1.  `required` 验证关键字要求使用 `type` 和 `price` 进行基本请求验证。

1. 模型的 `properties` 为 `id`、`type` 和 `price`。每个对象都有模型中描述的属性。

1. 对象 `type` 只能具有值 `dog`、`cat` 或 `fish`。

1. 对象 `price` 是一个数字，并受 `minimum` 为 25 和 `maximum` 为 500 所限制。

## PetStore 模型
<a name="PetStore-model-text"></a>

```
1 {
2 "$schema": "http://json-schema.org/draft-04/schema#",
3  "title": "PetStoreModel",
4  "type" : "object",
5  "required" : [ "price", "type" ],
6  "properties" : {
7    "id" : {
8      "type" : "integer"
9    },
10    "type" : {
11      "type" : "string",
12      "enum" : [ "dog", "cat", "fish" ]
13    },
14    "price" : {
15      "type" : "number",
16      "minimum" : 25.0,
17      "maximum" : 500.0
18    }
19  }
20 }
```

在这个模型中：

1. 在第 2 行上，`$schema` 对象表示一个有效的 JSON 架构版本标识符。此架构为 JSON 架构草案 v4。

1. 在第 3 行上，`title` 对象是用户可读的模型标识符。此标题是 `PetStoreModel`。

1.  在第 5 行上，`required` 验证关键字要求使用 `type` 和 `price` 进行基本请求验证。

1.  在第 6 -- 17 行上，模型的 `properties` 为 `id`、`type` 和 `price`。每个对象都有模型中描述的属性。

1. 在第 12 行上，对象 `type` 只能具有值 `dog`、`cat` 或 `fish`。

1. 在第 14 -- 17 行上，对象 `price` 是一个数字，并受 `minimum` 为 25 和 `maximum` 为 500 所限制。

## 创建更复杂的模型
<a name="api-gateway-request-validation-model-more-complex"></a>

 您可以使用 `$ref` 基元为较长的模型创建可重复使用的定义。例如，可以在描述 `price` 对象的 `definitions` 部分中创建称为 `Price` 的定义。`$ref` 的值是 `Price` 定义。

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStoreModelReUsableRef",
  "required" : ["price", "type" ],
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "type" : {
      "type" : "string",
      "enum" : [ "dog", "cat", "fish" ]
    },
    "price" : {
        "$ref": "#/definitions/Price"
    }
  },
  "definitions" : {
      "Price": {
        "type" : "number",
        "minimum" : 25.0,
        "maximum" : 500.0
            }
      }
}
```

您也可以引用在外部模型文件中定义的另一个模型架构。将 `$ref` 属性的值设置为模型的位置。在以下示例中，`Price` 模型是在 API `a1234` 的 `PetStorePrice` 模型中定义的。

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStorePrice",
  "type": "number",
  "minimum": 25,
  "maximum": 500
}
```

较长的模型可以引用 `PetStorePrice` 模型。

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStoreModelReusableRefAPI",
  "required" : [ "price", "type" ],
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "type" : {
      "type" : "string",
      "enum" : [ "dog", "cat", "fish" ]
    },
    "price" : {
        "$ref": "https://apigateway.amazonaws.com/restapis/a1234/models/PetStorePrice"
    }
  }
}
```

## 使用输出数据模型
<a name="api-gateway-request-validation-output-model"></a>

如果您转换数据，则可以在集成响应中定义负载模型。生成 SDK 时可以使用负载模型。对于强类型语言（如 Java、Objective-C 或 Swift），对象对应于用户定义的数据类型 (UDT)。如果您在生成 SDK 时向其提供数据模型，API Gateway 将创建 UDT。有关数据转换的更多信息，请参阅[API Gateway 中 REST API 的映射模板转换](models-mappings.md)。

以下示例是来自集成响应的输出数据。

```
{
[
  {
    "description" : "Item 1 is a dog.",
    "askingPrice" : 249.99
  },
  {
    "description" : "Item 2 is a cat.",
    "askingPrice" : 124.99
  },
  {
    "description" : "Item 3 is a fish.",
    "askingPrice" : 0.99
  }
]
}
```

以下示例是描述输出数据的负载模型。

```
{
"$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PetStoreOutputModel",
  "type" : "object",
  "required" : [ "description", "askingPrice" ],
  "properties" : {
    "description" : {
      "type" : "string"
    },
    "askingPrice" : {
      "type" : "number",
      "minimum" : 25.0,
      "maximum" : 500.0
    }
  }
}
```

借助此模型，您可以调用 SDK，以便通过读取 `PetStoreOutputModel[i].description` 和 `PetStoreOutputModel[i].askingPrice` 属性来检索 `description` 和 `askingPrice` 属性值。如果未提供模型，API Gateway 将使用空模型创建默认 UDT。

## 后续步骤
<a name="api-gateway-request-validation-model-next-steps"></a>
+ 本节提供的资源可用于获得有关本主题中介绍的概念的更多知识。

  您可以按照请求验证教程进行操作：
  + [使用 API Gateway 控制台设置请求验证](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-in-console)
  +  [使用 AWS CLI 设置基本请求验证](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-cli)
  +  [使用 OpenAPI 定义设置基本请求验证](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-importing-swagger)
+  有关数据转换和映射模板的更多信息，请参阅[API Gateway 中 REST API 的映射模板转换](models-mappings.md)。

# 在 API Gateway 中设置基本请求验证
<a name="api-gateway-request-validation-set-up"></a>

 本节介绍如何使用控制台、AWS CLI 和 OpenAPI 定义为 API Gateway 设置请求验证。

**Topics**
+ [使用 API Gateway 控制台设置请求验证](#api-gateway-request-validation-setup-in-console)
+ [使用 AWS CLI 设置基本请求验证](#api-gateway-request-validation-setup-cli)
+ [使用 OpenAPI 定义设置基本请求验证](#api-gateway-request-validation-setup-importing-swagger)

## 使用 API Gateway 控制台设置请求验证
<a name="api-gateway-request-validation-setup-in-console"></a>

 您可以使用 API Gateway 控制台从 API 请求的三个验证程序中选择一个来验证请求：
+ **验证正文**。
+ **验证查询字符串参数和标头**。
+ **验证正文、查询字符串参数和标头**。

 当您对 API 方法应用以上一种验证程序时，API Gateway 控制台会向 API 的 [RequestValidators](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html) 映射添加该验证程序。

要按本教程操作，您将使用 CloudFormation 模板来创建不完整的 API Gateway API。此 API 拥有的 `/validator` 资源具有 `GET` 和 `POST` 方法。两种方法都与 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点集成。您将配置两种请求验证：
+ 在 `GET` 方法中，您将为 URL 查询字符串参数配置请求验证。
+ 在 `POST` 方法中，您将为请求正文配置请求验证。

 这将只允许特定的 API 调用传递给 API。

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/request-validation-tutorial-console.zip)。您将使用此模板创建不完整的 API。您将在 API Gateway 控制台中完成其余步骤。

**创建 CloudFormation 堆栈**

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

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

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

1. 选择您下载的模板。

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

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

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

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

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

CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。当 CloudFormation 堆栈的状态为 **CREATE\$1COMPLETE** 时，您就可以继续下一步了。

**选择您新创建的 API**

1. 选择新创建的 **request-validation-tutorial-console** 堆栈。

1. 选择**资源**。

1. 在**物理 ID** 下，选择您的 API。此链接将引导您进入 API Gateway 控制台。

在修改 `GET` 和 `POST` 方法之前，必须创建模型。

**创建模型**

1. 需要一个模型来对传入请求的正文使用请求验证。要创建模型，请在主导航窗格中选择**模型**。

1. 选择**创建模型**。

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

1. 对于**内容类型**，输入 **application/json**。如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请输入 **\$1default**。

1. 对于**描述**，输入 **My PetStore Model** 作为模型描述。

1. 对于**模型架构**，将以下模型粘贴到代码编辑器中，然后选择**创建**。

   ```
   {
     "type" : "object",
     "required" : [ "name", "price", "type" ],
     "properties" : {
       "id" : {
         "type" : "integer"
       },
       "type" : {
         "type" : "string",
         "enum" : [ "dog", "cat", "fish" ]
       },
       "name" : {
         "type" : "string"
       },
       "price" : {
         "type" : "number",
         "minimum" : 25.0,
         "maximum" : 500.0
       }
     }
   }
   ```

有关模型的更多信息，请参阅[针对 REST API 的数据模型](models-mappings-models.md)。

**为 `GET` 方法配置请求验证**

1. 在主导航窗格中，选择**资源**，然后选择 **GET** 方法。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**请求验证程序**，选择**验证查询字符串参数和标头**。

1. 在 **URL 查询字符串参数**下，执行以下操作：

   1. 选择**添加查询字符串**。

   1. 在**名称**中，输入 **petType**。

   1. 打开**必需**。

   1. 将**缓存**保持为关闭状态。

1. 选择**保存**。

1. 在**集成请求**选项卡的**集成请求设置**下，选择**编辑**。

1. 在 **URL 查询字符串参数**下，执行以下操作：

   1. 选择**添加查询字符串**。

   1. 在**名称**中，输入 **petType**。

   1. 对于**映射自**，输入 **method.request.querystring.petType**。这会将 **petType** 映射到宠物的类型。

      有关数据映射的更多信息，请参阅[数据映射教程](set-up-data-transformations-in-api-gateway.md#mapping-example-console)。

   1. 将**缓存**保持为关闭状态。

1. 选择**保存**。

**为 `GET` 方法测试请求验证**

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

1. 对于**查询字符串**，输入 **petType=dog**，然后选择**测试**。

1. 方法测试将返回 `200 OK` 并提供狗的列表。

   有关如何转换此输出数据的信息，请参阅[数据映射教程](set-up-data-transformations-in-api-gateway.md#mapping-example-console)。

1. 删除 **petType=dog** 并选择**测试**。

1.  方法测试将返回 `400` 错误并显示以下错误消息：

   ```
   {
     "message": "Missing required request parameters: [petType]"
   }
   ```

**为 `POST` 方法配置请求验证**

1. 在主导航窗格中，选择**资源**，然后选择 **POST** 方法。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**请求验证程序**，选择**验证正文**。

1. 在**请求正文**下，选择**添加模型**。

1. 对于**内容类型**，输入 **application/json**。如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请输入 `$default`。

    对于**模型**，请选择 **PetStoreModel**。

1. 选择**保存**。

**为 `POST` 方法测试请求验证**

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

1. 对于**请求正文**，将以下内容粘贴到代码编辑器中：

   ```
   {
     "id": 2,
     "name": "Bella",
     "type": "dog",
     "price": 400
   }
   ```

    选择**测试**。

1. 方法测试将返回 `200 OK` 和成功消息。

1. 对于**请求正文**，将以下内容粘贴到代码编辑器中：

   ```
   {
     "id": 2,
     "name": "Bella",
     "type": "dog",
     "price": 4000
   }
   ```

    选择**测试**。

1.  方法测试将返回 `400` 错误并显示以下错误消息：

   ```
   {
    "message": "Invalid request body"
   }
   ```

    在测试日志的底部，将返回请求正文无效的原因。在这种情况下，宠物的价格超出了模型中规定的最高价格。

**删除 CloudFormation 堆栈**

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

1. 选择您的 CloudFormation 堆栈。

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

### 后续步骤
<a name="next-steps-request-validation-tutorial"></a>
+ 有关如何转换输出数据和执行更多数据映射的信息，请参阅[数据映射教程](set-up-data-transformations-in-api-gateway.md#mapping-example-console)。
+ 按照[使用 AWS CLI 设置基本请求验证](#api-gateway-request-validation-setup-cli)教程操作，使用 AWS CLI 执行类似的步骤。

## 使用 AWS CLI 设置基本请求验证
<a name="api-gateway-request-validation-setup-cli"></a>

您可以使用 AWS CLI 创建验证程序来设置请求验证。要按本教程操作，您将使用 CloudFormation 模板来创建不完整的 API Gateway API。

**注意**  
这与控制台教程的 CloudFormation 模板不同。

 使用预先公开的 `/validator` 资源，您将创建 `GET` 和 `POST` 方法。两种方法都将与 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点集成。您将配置以下两个请求验证：
+ 在 `GET` 方法上，您将创建一个 `params-only` 验证程序来验证 URL 查询字符串参数。
+ 在 `POST` 方法上，您将创建一个 `body-only` 验证程序来验证请求正文。

 这将只允许特定的 API 调用传递给 API。

**创建 CloudFormation 堆栈**

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/request-validation-tutorial-cli.zip)。

要完成以下教程，您需要 [AWS Command Line Interface（AWS CLI）版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

对于长命令，使用转义字符 (`\`) 将命令拆分为多行。
**注意**  
在 Windows 中，操作系统的内置终端不支持您经常使用的某些 Bash CLI 命令（例如 `zip`）。[安装 Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install)，获取 Ubuntu 和 Bash 与 Windows 集成的版本。本指南中的示例 CLI 命令使用 Linux 格式。如果您使用的是 Windows CLI，则必须重新格式化包含内联 JSON 文档的命令。

1.  输入以下命令创建 CloudFormation 堆栈。

   ```
   aws cloudformation create-stack --stack-name request-validation-tutorial-cli --template-body file://request-validation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。使用以下命令查看 CloudFormation 的状态。

   ```
   aws cloudformation describe-stacks --stack-name request-validation-tutorial-cli
   ```

1. 当 CloudFormation 堆栈的状态为 `StackStatus: "CREATE_COMPLETE"` 时，使用以下命令检索将来步骤的相关输出值。

   ```
    aws cloudformation describe-stacks --stack-name request-validation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   输出值包括：
   + ApiId，这是 API 的 ID。对于本教程，API ID 为 `abc123`。
   + ResourceId，这是在其中公开 `GET` 和 `POST` 方法的验证程序资源的 ID。对于本教程，资源 ID 为 `efg456`

**创建请求验证程序并导入模型**

1. 需要验证程序才能通过 AWS CLI 使用请求验证。使用以下命令创建仅验证请求参数的验证程序。

   ```
   aws apigateway create-request-validator --rest-api-id abc123 \
         --no-validate-request-body \
         --validate-request-parameters \
         --name params-only
   ```

   记下 `params-only` 验证程序的 ID。

1.  使用以下命令创建仅验证请求正文的验证程序。

   ```
   aws apigateway create-request-validator --rest-api-id abc123 \
         --validate-request-body \
         --no-validate-request-parameters \
         --name body-only
   ```

   记下 `body-only` 验证程序的 ID。

1.  需要一个模型来对传入请求的正文使用请求验证。使用以下命令导入模型。

   ```
   aws apigateway create-model --rest-api-id abc123 --name PetStoreModel --description 'My PetStore Model' --content-type 'application/json' --schema '{"type": "object", "required" : [ "name", "price", "type" ], "properties" : { "id" : {"type" : "integer"},"type" : {"type" : "string", "enum" : [ "dog", "cat", "fish" ]},"name" : { "type" : "string"},"price" : {"type" : "number","minimum" : 25.0, "maximum" : 500.0}}}}' 
   ```

   如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请指定 `$default` 作为键。

**创建 `GET` 和 `POST` 方法**

1. 使用以下命令对 `/validate` 资源添加 `GET` HTTP 方法。此命令创建 `GET` 方法，添加 `params-only` 验证程序，并根据需要设置查询字符串 `petType`。

   ```
   aws apigateway put-method --rest-api-id abc123 \
          --resource-id efg456 \
          --http-method GET \
          --authorization-type "NONE" \
          --request-validator-id aaa111 \
          --request-parameters "method.request.querystring.petType=true"
   ```

   使用以下命令对 `/validate` 资源添加 `POST` HTTP 方法。此命令创建 `POST` 方法，添加 `body-only` 验证程序，并将模型附加到仅限正文的验证程序。

   ```
   aws apigateway put-method --rest-api-id abc123 \
          --resource-id efg456 \
          --http-method POST \
          --authorization-type "NONE" \
          --request-validator-id bbb222 \
          --request-models 'application/json'=PetStoreModel
   ```

1.  使用以下命令设置 `GET /validate` 方法的 `200 OK` 响应。

   ```
   aws apigateway put-method-response --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method GET \
               --status-code 200
   ```

    使用以下命令设置 `POST /validate` 方法的 `200 OK` 响应。

   ```
   aws apigateway put-method-response --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method POST \
               --status-code 200
   ```

1.  使用以下命令通过指定的 HTTP 端点为 `GET /validation` 方法设置 `Integration`。

   ```
   aws apigateway put-integration --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method GET \
               --type HTTP \
               --integration-http-method GET \
               --request-parameters '{"integration.request.querystring.type" : "method.request.querystring.petType"}' \
               --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   ```

    使用以下命令通过指定的 HTTP 端点为 `POST /validation` 方法设置 `Integration`。

   ```
   aws apigateway put-integration --rest-api-id abc123  \
                 --resource-id efg456 \
                 --http-method POST \
                 --type HTTP \
                 --integration-http-method GET \
                 --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   ```

1.  使用以下命令设置 `GET /validation` 方法的集成响应。

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
                 --resource-id efg456\
                 --http-method GET \
                 --status-code 200 \
                 --selection-pattern ""
   ```

    使用以下命令设置 `POST /validation` 方法的集成响应。

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method POST \
               --status-code 200 \
               --selection-pattern ""
   ```

**测试 API**

1. 要测试将对查询字符串执行请求验证的 `GET` 方法，请使用以下命令：

   ```
   aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method GET \
               --path-with-query-string '/validate?petType=dog'
   ```

   结果将返回 `200 OK` 和狗的列表。

1. 使用以下命令在不包含查询字符串 `petType` 的情况下进行测试

   ```
   aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method GET
   ```

   结果将返回 `400` 错误。

1. 要测试将对请求正文执行请求验证的 `POST` 方法，请使用以下命令：

   ```
    aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method POST \
               --body '{"id": 1, "name": "bella", "type": "dog", "price" : 400 }'
   ```

   结果将返回 `200 OK` 和一条成功消息。

1. 使用以下命令通过无效的正文进行测试。

   ```
    aws apigateway test-invoke-method --rest-api-id abc123 \
                 --resource-id efg456 \
                 --http-method POST \
                 --body '{"id": 1, "name": "bella", "type": "dog", "price" : 1000 }'
   ```

   结果将返回 `400` 错误，因为狗的价格超过了模型定义的最高价格。

**删除 CloudFormation 堆栈**
+ 使用以下命令删除您的 CloudFormation 资源。

  ```
  aws cloudformation delete-stack  --stack-name request-validation-tutorial-cli
  ```

## 使用 OpenAPI 定义设置基本请求验证
<a name="api-gateway-request-validation-setup-importing-swagger"></a>

 您可以在 API 级别声明请求验证程序，方法是在 [x-amazon-apigateway-request-validators 对象](api-gateway-swagger-extensions-request-validators.md) 映射中指定一组 [x-amazon-apigateway-request-validators.requestValidator 对象](api-gateway-swagger-extensions-request-validators.requestValidator.md) 对象，以选择将对请求的哪个部分进行验证。在示例 OpenAPI 定义中，有两个验证程序：
+ `all` 验证程序，它验证正文（使用 `RequestBodyModel` 数据模型）和参数。

  `RequestBodyModel` 数据模型要求输入 JSON 对象包含 `name`、`type` 和 `price` 属性。`name` 属性可以是任何字符串，`type` 必须是一种指定枚举字段 (`["dog", "cat", "fish"]`)，而 `price` 必须介于 25 和 500 之间。`id` 参数不是必需参数。
+ `param-only`，它只验证参数。

 要在 API 的所有方法上开启请求验证程序，请在 API 级别指定 OpenAPI 定义的 [x-amazon-apigateway-request-validator 属性](api-gateway-swagger-extensions-request-validator.md) 属性。在示例 OpenAPI 定义中，`all` 验证器用于所有 API 方法，除非被覆盖。使用模型验证正文时，如果找不到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请指定 `$default` 作为键。

要针对单独的方法开启请求验证程序，请在方法级别指定 `x-amazon-apigateway-request-validator` 属性。在示例 OpenAPI 定义中，`param-only` 验证程序会覆盖 `GET` 方法上的 `all` 验证程序。



要将 OpenAPI 示例导入 API Gateway，请参阅以下有关[将区域 API 导入到 API Gateway 中](import-export-api-endpoints.md)或[将边缘优化的 API 导入 API Gateway](import-edge-optimized-api.md)的说明。

------
#### [ OpenAPI 3.0 ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "ReqValidators Sample",
    "version" : "1.0.0"
  },
  "servers" : [ {
    "url" : "/{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "/v1"
      }
    }
  } ],
  "paths" : {
    "/validation" : {
      "get" : {
        "parameters" : [ {
          "name" : "q1",
          "in" : "query",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "test-method-response-header" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ArrayOfError"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "params-only",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.type" : "method.request.querystring.q1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      },
      "post" : {
        "parameters" : [ {
          "name" : "h1",
          "in" : "header",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RequestBodyModel"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "test-method-response-header" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ArrayOfError"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "all",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "POST",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.custom_h1" : "method.request.header.h1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "RequestBodyModel" : {
        "required" : [ "name", "price", "type" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string",
            "enum" : [ "dog", "cat", "fish" ]
          },
          "name" : {
            "type" : "string"
          },
          "price" : {
            "maximum" : 500.0,
            "minimum" : 25.0,
            "type" : "number"
          }
        }
      },
      "ArrayOfError" : {
        "type" : "array",
        "items" : {
          "$ref" : "#/components/schemas/Error"
        }
      },
      "Error" : {
        "type" : "object"
      }
    }
  },
  "x-amazon-apigateway-request-validators" : {
    "all" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : true
    },
    "params-only" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : false
    }
  }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger" : "2.0",
  "info" : {
    "version" : "1.0.0",
    "title" : "ReqValidators Sample"
  },
  "basePath" : "/v1",
  "schemes" : [ "https" ],
  "paths" : {
    "/validation" : {
      "get" : {
        "produces" : [ "application/json", "application/xml" ],
        "parameters" : [ {
          "name" : "q1",
          "in" : "query",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/ArrayOfError"
            },
            "headers" : {
              "test-method-response-header" : {
                "type" : "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "params-only",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.type" : "method.request.querystring.q1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      },
      "post" : {
        "consumes" : [ "application/json" ],
        "produces" : [ "application/json", "application/xml" ],
        "parameters" : [ {
          "name" : "h1",
          "in" : "header",
          "required" : true,
          "type" : "string"
        }, {
          "in" : "body",
          "name" : "RequestBodyModel",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/RequestBodyModel"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/ArrayOfError"
            },
            "headers" : {
              "test-method-response-header" : {
                "type" : "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "all",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "POST",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.custom_h1" : "method.request.header.h1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "definitions" : {
    "RequestBodyModel" : {
      "type" : "object",
      "required" : [ "name", "price", "type" ],
      "properties" : {
        "id" : {
          "type" : "integer"
        },
        "type" : {
          "type" : "string",
          "enum" : [ "dog", "cat", "fish" ]
        },
        "name" : {
          "type" : "string"
        },
        "price" : {
          "type" : "number",
          "minimum" : 25.0,
          "maximum" : 500.0
        }
      }
    },
    "ArrayOfError" : {
      "type" : "array",
      "items" : {
        "$ref" : "#/definitions/Error"
      }
    },
    "Error" : {
      "type" : "object"
    }
  },
  "x-amazon-apigateway-request-validators" : {
    "all" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : true
    },
    "params-only" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : false
    }
  }
}
```

------

# AWS CloudFormation 模板，提供带有基本请求验证的示例 API
<a name="api-gateway-request-validation-sample-cloudformation"></a>

 以下 CloudFormation 示例模板定义一个启用了请求验证的示例 API。该 API 是 [PetStore API](http://petstore-demo-endpoint.execute-api.com/petstore/pets) 的一部分。其使用 `POST` 方法将宠物添加到 `pets` 集合，并使用 `GET` 方法按指定类型查询宠物。

 其中声明了两个请求验证程序：

**`GETValidator`**  
此验证程序已在 `GET` 方法上启用。它允许 API Gateway 验证所需的查询参数 (`q1`) 是否包含在传入请求内且不为空。

**`POSTValidator`**  
此验证程序已在 `POST` 方法上启用。它允许 API Gateway 在内容类型为 `application/json` 时，验证负载请求格式是否遵循指定的 `RequestBodyModel`，如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请指定`$default`。`RequestBodyModel` 包含一个额外的模型 `RequestBodyModelId`，用于定义宠物 ID。

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: ReqValidatorsSample
  RequestBodyModelId:
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref Api
      ContentType: application/json
      Description: Request body model for Pet ID.
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: RequestBodyModelId
        properties:
            id:
              type: integer
  RequestBodyModel: 
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref Api
      ContentType: application/json
      Description: Request body model for Pet type, name, price, and ID.
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: RequestBodyModel
        required:
          - price
          - name
          - type
        type: object
        properties:
            id:
              "$ref": !Sub 
                - 'https://apigateway.amazonaws.com/restapis/${Api}/models/${RequestBodyModelId}'
                - Api: !Ref Api
                  RequestBodyModelId: !Ref RequestBodyModelId
            price: 
              type: number
              minimum: 25
              maximum: 500
            name:
              type: string
            type:
              type: string
              enum:
                - "dog"
                - "cat"
                - "fish"
  GETValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: params-only
      RestApiId: !Ref Api
      ValidateRequestBody: False
      ValidateRequestParameters: True 
  POSTValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: body-only
      RestApiId: !Ref Api
      ValidateRequestBody: True
      ValidateRequestParameters: False
  ValidationResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'validation'
  ValidationMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref ValidationResource
      HttpMethod: GET
      AuthorizationType: NONE
      RequestValidatorId: !Ref GETValidator
      RequestParameters:
        method.request.querystring.q1: true
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ValidationMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref ValidationResource
      HttpMethod: POST
      AuthorizationType: NONE
      RequestValidatorId: !Ref POSTValidator
      RequestModels:
        application/json : !Ref RequestBodyModel 
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: POST
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - ValidationMethodGet
      - RequestBodyModel 
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiRootUrl:
    Description: Root Url of the API
    Value: !Sub 'https://${Api}.execute-api.${AWS::Region}.amazonaws.com/${StageName}'
```

# 针对 API Gateway 中 REST API 的数据转换
<a name="rest-api-data-transformations"></a>

**注意**  
本节介绍您在非代理集成中使用的功能。但是，我们建议您尽可能为 REST API 使用代理集成。代理集成具有简化的集成设置，可以随后端演变，而无需停用现有设置。有关更多信息，请参阅 [选择 API Gateway API 集成类型](api-gateway-api-integration-types.md)。

如果您使用非代理集成，则可以使用 API Gateway 的两个功能来转换方法请求和集成响应。如果方法请求采用的有效载荷格式与集成请求有效载荷不同，则可以对方法请求进行转换。如果集成响应返回的有效载荷格式与您需要在方法响应中返回的格式不同，则可以对集成响应进行转换。有关请求生命周期的更多信息，请参阅 [REST API 的示例资源](rest-api-develop.md#rest-api-develop-example)。

以下示例显示了一个数据转换，其中对于标头 `"x-version:beta"`，`x-version` 标头参数转换为 `app-version` 标头参数。从 `x-version` 到 `app-version` 的数据转换发生在集成请求中。这样，集成端点就会收到转换后的标头参数值。当集成端点返回状态代码时，状态代码将在方法响应之前从 `200` 转换为 `204`。

![\[API Gateway 数据转换图\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/develop-non-proxy.png)


要创建数据转换，可以使用以下功能：

**参数映射**  
在参数映射中，可以修改集成请求 URL 路径参数、URL 查询字符串参数或 HTTP 标头值，但不能修改集成请求有效载荷。也可以修改 HTTP 响应标头值。使用参数映射为跨源资源共享（CORS）创建静态标头值。  
您可以在代理和非代理集成的集成请求中使用参数映射，但要将参数映射用于集成响应，则需要非代理集成。参数映射不需要使用 [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) 编写任何脚本。有关更多信息，请参阅 [API Gateway 中 REST API 的参数映射](rest-api-parameter-mapping.md)。

**映射模板转换**  
在映射模板转换中，可以使用映射模板来映射 URL 路径参数、URL 查询字符串参数、HTTP 标头和集成请求或集成响应正文。**映射模板是使用 [JSONPath 表达式](https://goessner.net/articles/JsonPath/)以 [Velocity Template Language（VTL）](https://velocity.apache.org/engine/devel/vtl-reference.html)表示的脚本，并基于 `Content-type` 标头应用于有效载荷。  
使用映射模板，您可以执行以下操作：  
+ 选择要使用与 AWS 服务（例如 Amazon DynamoDB 或 Lambda 函数或 HTTP 端点）的集成发送哪些数据。有关更多信息，请参阅 [教程：修改集成请求和响应以集成到 AWS 服务](set-up-data-transformations-in-api-gateway.md)。
+ 有条件地覆盖 API 的集成请求和集成响应参数、创建新的标头值并覆盖状态代码。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。
当集成请求正文的 `Content-type` 标头没有匹配的映射模板时，还可以指定 API 的行为。这称为集成传递行为。有关更多信息，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

## 在参数映射与映射模板转换之间进行选择
<a name="rest-api-data-transformations-choose"></a>

我们建议您尽可能使用参数映射来转换数据。如果 API 要求您更改正文，或者要求您根据传入的集成请求或集成响应执行有条件覆盖和修改，并且您无法使用代理集成，请使用映射模板转换。

# API Gateway 中 REST API 的参数映射
<a name="rest-api-parameter-mapping"></a>

**注意**  
如果您使用的是 HTTP API，请参阅[针对 API Gateway 中的 HTTP API 转换 API 请求和响应](http-api-parameter-mapping.md)。

在参数映射中，您可以映射请求或响应参数。您可以使用参数映射表达式或静态值来映射参数。有关映射表达式的列表，请参阅 [API Gateway 中 REST API 的参数映射源参考](rest-api-parameter-mapping-sources.md)。您可以在代理和非代理集成的集成请求中使用参数映射，但要将参数映射用于集成响应，则需要非代理集成。

例如，您可以将方法请求标头参数 `puppies` 映射到集成请求标头参数 `DogsAge0`。然后，如果客户端将标头 `puppies:true` 发送到您的 API，则集成请求会将请求标头 `DogsAge0:true` 发送到集成端点。下图显示了此示例的请求生命周期。

![\[请求的 API Gateway 参数映射示例图\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/parameter-mapping-example1.png)


要使用 API Gateway 创建此示例，请参阅[示例 1：将方法请求参数映射到集成请求参数](request-response-data-mappings.md#request-response-data-mappings-example-1)。

 再举一个例子，您也可以将集成响应标头参数 `kittens` 映射到方法响应标头参数 `CatsAge0`。然后，如果集成端点返回 `kittens:false`，则客户端将收到标头 `CatsAge0:false`。下图显示了此示例的请求生命周期。

![\[响应的 API Gateway 参数映射示例图\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/parameter-mapping-example2.png)


**Topics**
+ [API Gateway 中 REST API 的参数映射示例](request-response-data-mappings.md)
+ [API Gateway 中 REST API 的参数映射源参考](rest-api-parameter-mapping-sources.md)

# API Gateway 中 REST API 的参数映射示例
<a name="request-response-data-mappings"></a>

以下示例显示如何使用 API Gateway 控制台、OpenAPI 和 CloudFormation 模板创建参数映射表达式。有关如何使用参数映射来创建所需 CORS 标头的示例，请参阅[针对 API Gateway 中的 REST API 的 CORS](how-to-cors.md)。

## 示例 1：将方法请求参数映射到集成请求参数
<a name="request-response-data-mappings-example-1"></a>

以下示例将方法请求标头参数 `puppies` 映射到集成请求标头参数 `DogsAge0`。

------
#### [ AWS 管理控制台 ]

**映射方法请求参数**

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

1. 选择一个 REST API。

1. 选择方法。

   您的方法必须具有非代理集成。

1. 对于**方法请求设置**，选择**编辑**。

1. 选择 **HTTP 请求标头**。

1. 选择**添加标头**。

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

1. 选择**保存**。

1. 选择**集成请求**选项卡，然后对于**集成请求设置**，选择**编辑**。

   AWS 管理控制台会自动为您添加从 `method.request.header.puppies ` 到 `puppies` 的参数映射，但您需要更改**名称**，以匹配集成端点所期望的请求标头参数。

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

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

以下步骤向您展示如何验证参数映射是否成功。

**（可选）测试参数映射**

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

1. 对于标头，输入 **puppies:true**。

1. 选择**测试**。

1. 在**日志**中，结果应该类似以下内容：

   ```
   Tue Feb 04 00:28:36 UTC 2025 : Method request headers: {puppies=true}
   Tue Feb 04 00:28:36 UTC 2025 : Method request body before transformations: 
   Tue Feb 04 00:28:36 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
   Tue Feb 04 00:28:36 UTC 2025 : Endpoint request headers: {DogsAge0=true, x-amzn-apigateway-api-id=abcd1234, Accept=application/json, User-Agent=AmazonAPIGateway_aaaaaaa, X-Amzn-Trace-Id=Root=1-abcd-12344}
   ```

   请求标头参数已从 `puppies` 更改为 `DogsAge0`。

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body:
        openapi: 3.0.1
        info:
          title: ParameterMappingExample
          version: "2025-02-04T00:30:41Z"
        paths:
          /pets:
            get:
              parameters:
                - name: puppies
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.DogsAge0: method.request.header.puppies
                passthroughBehavior: when_no_match
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "ParameterMappingExample",
    "version" : "2025-02-04T00:30:41Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "puppies",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.DogsAge0" : "method.request.header.puppies"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

## 示例 2：将多个方法请求参数映射到不同的集成请求参数
<a name="request-response-data-mappings-example-2"></a>

以下示例将多值方法请求查询字符串参数 `methodRequestQueryParam` 映射到集成请求查询字符串参数 `integrationQueryParam`，并将方法请求标头参数 `methodRequestHeaderParam` 映射到集成请求路径参数 `integrationPathParam`。

------
#### [ AWS 管理控制台 ]

**映射方法请求参数**

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

1. 选择一个 REST API。

1. 选择方法。

   您的方法必须具有非代理集成。

1. 对于**方法请求设置**，选择**编辑**。

1. 选择 **URL 查询字符串参数**。

1. 选择**添加查询字符串**。

1. 在**名称**中，输入 **methodRequestQueryParam**。

1. 选择 **HTTP 请求标头**。

1. 选择**添加标头**。

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

1. 选择**保存**。

1. 选择**集成请求**选项卡，然后对于**集成请求设置**，选择**编辑**。

1. 选择 **URL 路径参数**。

1. 选择**添加路径参数**。

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

1. 对于**映射自**，输入 **method.request.header.methodRequestHeaderParam**。

   这会将您在方法请求中指定的方法请求标头映射到新的集成请求路径参数。

1. 选择 **URL 查询字符串参数**。

1. 选择**添加查询字符串**。

1. 在**名称**中，输入 **integrationQueryParam**。

1. 对于**映射自**，输入 **method.request.multivaluequerystring.methodRequestQueryParam**。

   这会将多值查询字符串参数映射到新的单值集成请求查询字符串参数。

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

以下 OpenAPI 定义为 HTTP 集成创建以下参数映射：
+ 将方法请求的名为 `methodRequestHeaderParam` 的标头映射到名为 `integrationPathParam` 的集成请求路径参数
+ 将名为 `methodRequestQueryParam` 的多值方法请求查询字符串映射到名为 `integrationQueryParam` 的集成请求查询字符串

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: Parameter mapping example 2
          version: "2025-01-15T19:12:31Z"
        paths:
          /:
            post:
              parameters:
                - name: methodRequestQueryParam
                  in: query
                  schema:
                    type: string
                - name: methodRequestHeaderParam
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.querystring.integrationQueryParam: method.request.multivaluequerystring.methodRequestQueryParam
                  integration.request.path.integrationPathParam: method.request.header.methodRequestHeaderParam
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

以下 OpenAPI 定义为 HTTP 集成创建以下参数映射：
+ 将方法请求的名为 `methodRequestHeaderParam` 的标头映射到名为 `integrationPathParam` 的集成请求路径参数
+ 将名为 `methodRequestQueryParam` 的多值方法请求查询字符串映射到名为 `integrationQueryParam` 的集成请求查询字符串

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example 2",
    "version" : "2025-01-15T19:12:31Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "parameters" : [ {
          "name" : "methodRequestQueryParam",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "methodRequestHeaderParam",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.integrationQueryParam" : "method.request.multivaluequerystring.methodRequestQueryParam",
            "integration.request.path.integrationPathParam" : "method.request.header.methodRequestHeaderParam"
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000,
          "type" : "http"
        }
      }
    }
  }
}
```

------

## 示例 3：将 JSON 请求正文中的字段映射到集成请求参数
<a name="request-response-data-mappings-example-3"></a>

还可以使用 [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2) 从 JSON 请求正文中的字段映射集成请求参数。以下示例将方法请求正文映射到名为 `body-header` 的集成请求标头，并将部分请求正文（由 JSON 表达式表示）映射到名为 `pet-price` 的集成请求标头。

要测试此示例，请提供包含价格类别的输入，如下所示：

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

------
#### [ AWS 管理控制台 ]

**映射方法请求参数**

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

1. 选择一个 REST API。

1. 选择 `POST`、`PUT`、`PATCH` 或 `ANY` 方法。

   您的方法必须具有非代理集成。

1. 对于**集成请求设置**，选择**编辑**。

1. 选择 **URL 请求标头参数**。

1. 选择**添加请求标头参数**。

1. 对于**名称**，请输入 **body-header**。

1. 对于**映射自**，输入 **method.request.body**。

   这会将方法请求正文映射到新的集成请求标头参数。

1. 选择**添加请求标头参数**。

1. 对于**名称**，请输入 **pet-price**。

1. 对于**映射自**，输入 ** method.request.body[0].price**。

   这会将方法请求正文的一部分映射到新的集成请求标头参数。

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: Parameter mapping example 3
          version: "2025-01-15T19:19:14Z"
        paths:
          /:
            post:
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.pet-price: method.request.body[0].price
                  integration.request.header.body-header: method.request.body
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

以下 OpenAPI 定义从 JSON 请求正文中的字段映射集成请求参数。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example 3",
    "version" : "2025-01-15T19:19:14Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.pet-price" : "method.request.body[0].price",
            "integration.request.header.body-header" : "method.request.body"
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000,
          "type" : "http"
        }
      }
    }
  }
}
```

------

## 示例 4：将集成响应映射到方法响应
<a name="request-response-data-mappings-example-4"></a>

还可以将集成响应映射到方法响应。以下示例将集成响应正文映射到名为 `location` 的方法响应标头，将集成响应标头 `x-app-id` 映射到方法响应标头 `id`，并将多值集成响应标头 `item` 映射到方法响应标头 `items`。

------
#### [ AWS 管理控制台 ]

**映射集成响应**

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

1. 选择一个 REST API。

1. 选择方法。

   您的方法必须具有非代理集成。

1. 选择**方法响应**选项卡，然后对于**响应 200** 选择**编辑**。

1. 对于**标头名称**，选择**添加标头**。

1. 创建三个名为 **id**、**item**、和 **location** 的标头。

1. 选择**保存**。

1. 选择**集成响应**选项卡，然后对于**默认 - 响应**，选择**编辑**。

1. 在**标头映射**下，输入以下内容。

   1. 对于 **id**，输入 **integration.response.header.x-app-id**

   1. 对于**项目**，输入 **integration.response.multivalueheader.item**

   1. 对于**位置**，输入 **integration.response.body.redirect.url**

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body:
        openapi: 3.0.1
        info:
          title: Parameter mapping example
          version: "2025-01-15T19:21:35Z"
        paths:
          /:
            post:
              responses:
                "200":
                  description: 200 response
                  headers:
                    item:
                      schema:
                        type: string
                    location:
                      schema:
                        type: string
                    id:
                      schema:
                        type: string
              x-amazon-apigateway-integration:
                type: http
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                    responseParameters:
                      method.response.header.id: integration.response.header.x-app-id
                      method.response.header.location: integration.response.body.redirect.url
                      method.response.header.item: integration.response.multivalueheader.item
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

以下 OpenAPI 定义将集成响应映射到方法响应。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example",
    "version" : "2025-01-15T19:21:35Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "item" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "location" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "id" : {
                "schema" : {
                  "type" : "string"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "http",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.id" : "integration.response.header.x-app-id",
                "method.response.header.location" : "integration.response.body.redirect.url",
                "method.response.header.item" : "integration.response.multivalueheader.item"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000
        }
      }
    }
  }
}
```

------

# API Gateway 中 REST API 的参数映射源参考
<a name="rest-api-parameter-mapping-sources"></a>

创建参数映射时，可以指定要修改的方法请求或集成响应参数，并指定如何修改这些参数。

下表显示了可以映射的方法请求参数以及用于创建映射的表达式。在这些表达式中，*name* 是方法请求参数的名称。例如，要映射请求标头参数 `puppies`，请使用表达式 `method.request.header.puppies`。您的表达式必须与正则表达式 `'^[a-zA-Z0-9._$-]+$]'` 匹配。您可以在代理和非代理集成的集成请求中使用参数映射。


| **映射的数据来源** | **映射表达式** | 
| --- | --- | 
| 方法请求路径 | method.request.path.name | 
| 方法请求查询字符串 | method.request.querystring.name | 
| 多值方法请求查询字符串 | method.request.multivaluequerystring.name | 
| 方法请求标头 | method.request.header.name | 
| 多值方法请求标头 | method.request.multivalueheader.name | 
| 方法请求正文 | method.request.body | 
| 方法请求正文 (JsonPath) | `method.request.body.JSONPath_EXPRESSION`. *JSONPath\$1EXPRESSION* 是请求正文的 JSON 字段的 JSONPath 表达式。有关更多信息，请参阅 [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2)。  | 
| 阶段变量 | stageVariables.name | 
| 上下文变量 |  `context.name` 名称必须为[受支持的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)之一。 | 
| 静态值 | `'static_value'`. *static\$1value* 为字符串文本值，必须括在一对单引号内。例如 `'https://www.example.com'`。 | 

下表显示了可以映射的集成响应参数以及用于创建映射的表达式。在这些表达式中，*name* 是集成响应参数的名称。您可以从任何集成响应标头或集成响应正文、\$1context 变量或静态值映射方法响应标头。要将参数映射用于集成响应，您需要使用非代理集成。


| 映射数据源 | 映射表达式 | 
| --- | --- | 
| 集成响应标头 | integration.response.header.name | 
| 集成响应标头 | integration.response.multivalueheader.name | 
| 集成响应正文 | integration.response.body | 
| 集成响应正文 (JsonPath) | `integration.response.body.JSONPath_EXPRESSION` *JSONPath\$1EXPRESSION* 是响应正文的 JSON 字段的 JSONPath 表达式。有关更多信息，请参阅 [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2)。 | 
| 阶段变量 | stageVariables.name | 
| 上下文变量 |  `context.name` 名称必须为[受支持的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)之一。 | 
| 静态值 | ` 'static_value'` *static\$1value* 为字符串文本值，必须括在一对单引号内。例如 `'https://www.example.com'`。 | 

# API Gateway 中 REST API 的映射模板转换
<a name="models-mappings"></a>

映射模板转换使用映射模板来修改集成请求或集成响应。**映射模板是以 [Velocity Template Language（VTL）](https://velocity.apache.org/engine/devel/vtl-reference.html)表示的脚本，并使用 [JSONPath](https://goessner.net/articles/JsonPath/) 基于 `Content-type` 标头应用于有效载荷。使用映射模板转换时使用映射模板。此部分介绍与映射模板相关的概念性信息。

下图显示了与 PetStore 集成端点集成的 `POST /pets` 资源的请求生命周期。在此 API 中，用户发送有关宠物的数据，而集成端点返回与宠物关联的收养费。在此请求生命周期中，映射模板转换会将请求正文筛选到集成端点，并从集成端点筛选响应正文。

![\[请求生命周期示例\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/mapping-template-transforms.png)


以下各节解释请求和响应生命周期。

## 方法请求和集成请求
<a name="models-mappings-request"></a>

在前面的示例中，如果这是发送到方法请求的请求正文：

```
POST /pets
    HTTP/1.1
    Host:abcd1234.us-west-2.amazonaws.com
    Content-type: application/json
    
  {
    "id": 1,
    "type": "dog",
    "Age": 11,
  }
```

此请求正文的格式不适合集成端点使用，因此 API Gateway 执行映射模板转换。API Gateway 仅执行映射模板转换，因为已为 Content-Type `application/json` 定义了映射模板。如果您没有为 Content-Type 定义映射模板，则默认情况下，API Gateway 会通过集成请求将正文传递到集成端点。要修改此行为，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

以下映射模板先转换集成请求中的方法请求数据，然后将数据发送到集成端点：

```
#set($inputRoot = $input.path('$'))
  {
    "dogId" : "dog_"$elem.id,
    "Age": $inputRoot.Age
  }
```

1. `$inputRoot` 变量表示上一部分的原始 JSON 数据中的根对象。指令以 `#` 符号开头。

1. `dog` 是用户的 `id` 和字符串值的串联。

1. `Age` 来自方法请求正文。

然后，将以下输出转发到集成端点：

```
{
    "dogId" : "dog_1",
    "Age": 11
  }
```

## 集成响应和方法响应
<a name="models-mappings-response"></a>

成功请求集成端点后，端点会向 API Gateway 的集成响应发送响应。以下是来自集成端点的示例输出数据：

```
{
    "dogId" : "dog_1",
    "adoptionFee": 19.95,
}
```

方法响应预期的有效载荷与集成响应返回的有效载荷不同。API Gateway 执行映射模板转换。API Gateway 仅执行映射模板转换，因为已为 Content-Type `application/json` 定义了映射模板。如果您没有为 Content-Type 定义映射模板，则默认情况下，API Gateway 会通过对方法响应的集成响应传递正文。要修改此行为，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

```
#set($inputRoot = $input.path('$'))
  {
    "adoptionFee" : $inputRoot.adoptionFee,
  }
```

以下输出发送到方法响应：

```
{"adoptionFee": 19.95}
```

这就完成了示例映射模板转换。我们建议尽可能使用代理集成来转换数据，而不是使用映射模板转换。有关更多信息，请参阅 [选择 API Gateway API 集成类型](api-gateway-api-integration-types.md)。

# API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为
<a name="integration-passthrough-behaviors"></a>

如果方法请求有一个有效载荷，而您没有为 `Content-Type` 标头定义映射模板，则可以选择通过集成请求将客户端提供的请求有效载荷传递到后端，而不进行转换。此过程称为集成传递。

 传入请求的实际传递行为由此设置决定。这里有三个选项：

**当没有模板与请求的 Content-Type 标头匹配时**  
如果您希望在方法请求内容类型不匹配任何与映射模板关联的内容类型时，将方法请求正文通过集成请求发送到后端而不进行转换，则选择此选项。  
调用 API Gateway API 时，您通过将 `WHEN_NO_MATCH` 设置为[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)的 `passthroughBehavior` 属性值来选择此选项。

**未定义任何模板时（推荐）**  
如果您希望在集成请求中未定义映射模板时，将方法请求正文通过集成请求发送到后端而不进行转换，则选择此选项。如果在选择此选项时定义了模板，则具有与任何定义的映射模板都不匹配的有效载荷和内容类型的方法请求将遭到拒绝，并返回“HTTP 415 媒体类型不受支持”响应。  
调用 API Gateway API 时，您通过将 `WHEN_NO_TEMPLATES` 设置为[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)的 `passthroughBehavior` 属性值来选择此选项。

**从不**  
如果您不希望在集成请求中未定义映射模板时，将方法请求正文通过集成请求发送到后端而不进行转换，则选择此选项。如果选择此选项时定义了模板，则会以“HTTP 415 Unsupported Media Type”响应拒绝未映射内容类型的方法请求。  
调用 API Gateway API 时，您通过将 `NEVER` 设置为[集成](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html)的 `passthroughBehavior` 属性值来选择此选项。

 以下示例显示了可能的传递行为。

示例 1：`application/json` 内容类型的集成请求中定义了一个映射模板。


| Content-type | 传递选项 | 行为 | 
| --- | --- | --- | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1MATCH | 使用模板转换请求负载。 | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1TEMPLATES | 使用模板转换请求负载。 | 
| 无 API Gateway 默认为 `application/json` | NEVER | 使用模板转换请求负载。 | 
| application/json | WHEN\$1NO\$1MATCH | 使用模板转换请求负载。 | 
| application/json | WHEN\$1NO\$1TEMPLATES | 使用模板转换请求负载。 | 
| application/json | NEVER | 使用模板转换请求负载。 | 
| application/xml | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/xml | WHEN\$1NO\$1TEMPLATES | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/xml | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 

示例 2：`application/xml` 内容类型的集成请求中定义了一个映射模板。


| Content-type | 传递选项 | 行为 | 
| --- | --- | --- | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1TEMPLATES | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| 无 API Gateway 默认为 `application/json` | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/json | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/json | WHEN\$1NO\$1TEMPLATES | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/json | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/xml | WHEN\$1NO\$1MATCH | 使用模板转换请求负载。 | 
| application/xml | WHEN\$1NO\$1TEMPLATES | 使用模板转换请求负载。 | 
| application/xml | NEVER | 使用模板转换请求负载。 | 

示例 3：集成请求中未定义映射模板。


| Content-type | 传递选项 | 行为 | 
| --- | --- | --- | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| 无 API Gateway 默认为 `application/json` | WHEN\$1NO\$1TEMPLATES | 请求负载未转换，并按原样发送到后端。 | 
| 无 API Gateway 默认为 `application/json` | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/json | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/json | WHEN\$1NO\$1TEMPLATES | 请求负载未转换，并按原样发送到后端。 | 
| application/json | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 
| application/xml | WHEN\$1NO\$1MATCH | 请求负载未转换，并按原样发送到后端。 | 
| application/xml | WHEN\$1NO\$1TEMPLATES | 请求负载未转换，并按原样发送到后端。 | 
| application/xml | NEVER | 请求被拒绝，得到 HTTP 415 Unsupported Media Type 响应。 | 

# API Gateway 中 REST API 的附加映射模板示例
<a name="example-photos"></a>

以下示例显示了 API Gateway 中的相册 API，该 API 使用映射模板转换集成请求和集成响应数据。它还使用数据模型来定义方法请求和集成响应有效载荷。有关数据模型的更多信息，请参阅[针对 REST API 的数据模型](models-mappings-models.md)。

## 方法请求和集成请求
<a name="example-photos-request"></a>

以下是定义方法请求正文的模型。此输入模型要求调用方上传一张照片页面，每页至少需要 10 张照片。您可以使用此输入模型生成 SDK 或为您的 API 使用请求验证。在使用请求验证时，如果方法请求正文不符合模型的数据结构，则 API Gateway 会使请求失败。

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosInputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "object",
      "required" : [
      "photo"
      ],
      "properties": {
        "page": { "type": "integer" },
        "pages": { "type": "string" },
        "perpage": { "type": "integer", "minimum" : 10 },
        "total": { "type": "string" },
        "photo": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "owner": { "type": "string" },
              "photographer_first_name" : {"type" : "string"},
              "photographer_last_name" : {"type" : "string"},
              "secret": { "type": "string" },
              "server": { "type": "string" },
              "farm": { "type": "integer" },
              "title": { "type": "string" },
              "ispublic": { "type": "boolean" },
              "isfriend": { "type": "boolean" },
              "isfamily": { "type": "boolean" }
            }
          }
        }
      }
    }
  }
}
```

以下是遵循先前数据模型的数据结构的方法请求正文示例。

```
{
  "photos": {
    "page": 1,
    "pages": "1234",
    "perpage": 100,
    "total": "123398",
    "photo": [
      {
        "id": "12345678901",
        "owner": "23456789@A12",
        "photographer_first_name" : "Saanvi",
        "photographer_last_name" : "Sarkar",
        "secret": "abc123d456",
        "server": "1234",
        "farm": 1,
        "title": "Sample photo 1",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      },
      {
        "id": "23456789012",
        "owner": "34567890@B23",
        "photographer_first_name" : "Richard",
        "photographer_last_name" : "Roe",
        "secret": "bcd234e567",
        "server": "2345",
        "farm": 2,
        "title": "Sample photo 2",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      }
    ]
  }
}
```

在此示例中，如果之前的方法请求正文是由客户端提交的，则此映射模板会转换有效载荷，以匹配集成端点所需的格式。

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.ispublic,
      "isfriend": $elem.isfriend,
      "isfamily": $elem.isfamily
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

以下示例是来自转换的输出数据：

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

这些数据发送到集成请求，然后发送到集成端点。

## 集成响应和方法响应
<a name="photos-example-response"></a>

以下是来自集成端点的照片数据的输出模型示例。您可以将此模型用于方法响应模型，这在为 API 生成强类型 SDK 时是必需的。这会导致输出将在 Java 或 Objective-C 中强制转换为适当的类。

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosOutputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "photographedBy": { "type": "string" },
          "title": { "type": "string" },
          "ispublic": { "type": "boolean" },
          "isfriend": { "type": "boolean" },
          "isfamily": { "type": "boolean" }
        }
      }
    }
  }
}
```

集成端点可能不会以符合此模型的数据结构的响应进行响应。例如，集成响应可能如下所示：

```
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    }		
  ]
}
```

以下示例映射模板将集成响应数据转换为方法响应所期望的格式：

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.public,
      "isfriend": $elem.friend,
      "isfamily": $elem.family
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

以下示例是来自转换的输出数据：

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

这些数据发送到方法响应，然后再发送回客户端。

# 针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码
<a name="apigateway-override-request-response-parameters"></a>

您可以使用映射模板转换来覆盖任何类型的请求参数、响应标头或响应状态代码。可以使用映射模板来执行以下操作：
+ 执行多对一参数映射
+ 在应用标准 API Gateway 映射后覆盖参数
+ 根据正文内容或其他参数值有条件地映射参数
+ 以编程方式创建新参数
+ 覆盖由集成端点返回的状态代码

覆盖是最终的。对于每个参数，覆盖只能应用一次。如果您多次尝试覆盖同一个参数，则 API Gateway 会返回 `5XX` 响应。如果您必须在整个模板中多次覆盖相同的参数，我们建议创建一个变量并在模板末尾应用覆盖。仅在解析整个模板后应用模板。

## 示例 1：基于集成正文覆盖状态代码
<a name="apigateway-override-request-response-examples"></a>

以下示例使用[示例 API](api-gateway-create-api-from-example.md) 基于集成响应正文覆盖状态代码。

------
#### [ AWS 管理控制台 ]

**基于集成响应正文覆盖状态代码**

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

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

1. 对于 **REST API**，选择**构建**。

1. 对于 **API 详细信息**，选择**示例 API**。

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

   API Gateway 创建一个示例宠物商店 API。要检索有关宠物的信息，您使用 API 方法请求 `GET /pets/{petId}`，其中 `{petId}` 是与宠物的 ID 号相对应的路径参数。

   在此示例中，当检测到错误条件时，您将 `GET` 方法的响应代码覆盖为 `400`。

1. 在**资源**树中，选择 `/{petId}` 下的 `GET` 方法。

1. 首先，测试 API 的当前实现。

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

1. 对于 **petId**，输入 **-1**，然后选择**测试**。

   **响应正文**指示超出范围错误：

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   此外，**日志**下的最后一行的结尾为：`Method completed with status: 200`。

   集成已成功完成，但出现错误。现在，您将根据集成响应覆盖状态代码。

1. 在**集成响应**选项卡上，对于**默认 - 响应**，选择**编辑**。

1. 选择**映射模板**。

1. 选择**添加映射模板**。

1. 对于**内容类型**，输入 **application/json**。

1. 对于**模板正文**，输入以下内容：

   ```
   #set($inputRoot = $input.path('$'))
   $input.json("$")
   #if($inputRoot.toString().contains("error"))
   #set($context.responseOverride.status = 400)
   #end
   ```

   如果集成响应包含字符串 `error`，则此映射模板使用 `$context.responseOverride.status` 变量将状态代码覆盖为 `400`。

1. 选择**保存**。

1. 选择**测试**选项卡。

1. 对于 **petId**，输入 **-1**。

1. 在结果中，**响应正文**表示超出范围错误：

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   不过，**日志**下的最后一行现在的结尾为：`Method completed with status: 400`。

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 1
          description: Example pet store API.
          version: "2025-01-14T00:13:18Z"
        paths:
          /pets/{petId}:
            get:
              parameters:
                - name: petId
                  in: path
                  required: true
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}
                responses:
                  default:
                    statusCode: "200"
                    responseTemplates:
                      application/json: |-
                        #set($inputRoot = $input.path('$'))
                        $input.json("$")
                        #if($inputRoot.toString().contains("error"))
                        #set($context.responseOverride.status = 400)
                        #end
                requestParameters:
                  integration.request.path.petId: method.request.path.petId
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

以下 OpenAPI 定义创建 `GET pets/{petId}` 资源并根据集成主体覆盖状态代码。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 1",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:13:18Z"
  },
  "paths" : {
    "/pets/{petId}" : {
      "get" : {
        "parameters" : [ {
          "name" : "petId",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n$input.json(\"$\")\n#if($inputRoot.toString().contains(\"error\"))\n#set($context.responseOverride.status = 400)\n#end"
              }
            }
          },
          "requestParameters" : {
            "integration.request.path.petId" : "method.request.path.petId"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Pet" : {
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string"
          },
          "price" : {
            "type" : "number"
          }
        }
      }
    }
  }
}
```

------

## 示例 2：覆盖请求标头并创建新标头
<a name="apigateway-override-request-response-examples-2"></a>

以下示例使用[示例 API](api-gateway-create-api-from-example.md) 来覆盖请求标头并创建新的标头。

------
#### [ AWS 管理控制台 ]

**通过创建新标头覆盖方法的请求标头**

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

1. 选择您在先前教程中创建的示例 API。API 的名称应为 **PetStore**。

1. 在**资源**树中，选择 `/pet` 下的 `GET` 方法。

1. 在**方法请求**选项卡上，对于**方法请求设置**，选择**编辑**。

1. 选择 **HTTP 请求标头**，然后选择**添加标头**。

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

1. 选择**添加标头**，然后创建第二个标头，名为 **header2**。

1. 选择**保存**。

   现在，您可以使用映射模板将这些标头合并为一个标头值。

1. 在**集成请求**选项卡上，对于**集成请求设置**，选择**编辑**。

1. 对于**请求正文传递**，选择**当未定义模板时（推荐）**。

1. 选择**映射模板**，然后执行以下操作：

   1. 选择**添加映射模板**。

   1. 对于**内容类型**，输入 **application/json**。

   1. 对于**模板正文**，输入以下内容：

      ```
      #set($header1Override = "pets")
      #set($header3Value = "$input.params('header1')$input.params('header2')")
      $input.json("$")
      #set($context.requestOverride.header.header3 = $header3Value)
      #set($context.requestOverride.header.header1 = $header1Override)
      #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
      ```

      此映射模板使用字符串 `pets` 覆盖 `header1`，并创建一个名为 `$header3Value` 的多值标头，该标头将 `header1` 和 `header2` 组合在一起。

1. 选择**保存**。

1. 选择**测试**选项卡。

1. 在**标头**下，复制以下代码：

   ```
   header1:header1Val
   header2:header2Val
   ```

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

   在**日志**中，您应看到一个包含此文本的条目：

   ```
   Endpoint request headers: {header3=header1Valheader2Val, 
   header2=header2Val, header1=pets, x-amzn-apigateway-api-id=api-id,
   Accept=application/json, multivalueheader=pets,header1Valheader2Val}
   ```

------
#### [ CloudFormation ]

 在此示例中，您使用 [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) 属性将 OpenAPI 定义文件导入到 API Gateway。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 2
          description: Example pet store API.
          version: "2025-01-14T00:36:18Z"
        paths:
          /pets:
            get:
              parameters:
                - name: header2
                  in: header
                  schema:
                    type: string
                - name: page
                  in: query
                  schema:
                    type: string
                - name: type
                  in: query
                  schema:
                    type: string
                - name: header1
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.header1: method.request.header.header1
                  integration.request.header.header2: method.request.header.header2
                  integration.request.querystring.page: method.request.querystring.page
                  integration.request.querystring.type: method.request.querystring.type
                requestTemplates:
                  application/json: |-
                    #set($header1Override = "pets")
                    #set($header3Value = "$input.params('header1')$input.params('header2')")
                    $input.json("$")
                    #set($context.requestOverride.header.header3 = $header3Value)
                    #set($context.requestOverride.header.header1 = $header1Override)
                    #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

 以下 OpenAPI 定义创建 `GET pets` 资源，并覆盖请求标头和创建新的标头。

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 2",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:36:18Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "header2",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "page",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "type",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "header1",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.header1" : "method.request.header.header1",
            "integration.request.header.header2" : "method.request.header.header2",
            "integration.request.querystring.page" : "method.request.querystring.page",
            "integration.request.querystring.type" : "method.request.querystring.type"
          },
          "requestTemplates" : {
            "application/json" : "#set($header1Override = \"pets\")\n#set($header3Value = \"$input.params('header1')$input.params('header2')\")\n$input.json(\"$\")\n#set($context.requestOverride.header.header3 = $header3Value)\n#set($context.requestOverride.header.header1 = $header1Override)\n#set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

要使用映射模板覆盖，请添加以下一个或多个 `$context` 变量。有关 `$context` 变量的列表，请参阅[数据转换的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)。

# 教程：修改集成请求和响应以集成到 AWS 服务
<a name="set-up-data-transformations-in-api-gateway"></a>

以下教程展示了如何使用映射模板转换来设置映射模板，以使用控制台和 AWS CLI 转换集成请求和响应。

**Topics**
+ [使用 API Gateway 控制台设置数据转换](#mapping-example-console)
+ [使用 AWS CLI 设置数据转换](#mapping-example-cli)
+ [已完成的数据转换 CloudFormation 模板](#api-gateway-data-transformations-full-cfn-stack)

## 使用 API Gateway 控制台设置数据转换
<a name="mapping-example-console"></a>

在本教程中，您将使用以下 .zip 文件 [data-transformation-tutorial-console.zip](samples/data-transformation-tutorial-console.zip) 创建不完整的 API 和 DynamoDB 表。这个不完整的 API 拥有的 `/pets` 资源具有 `GET` 和 `POST` 方法。
+ `GET` 方法将从 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点获取数据。输出数据将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板进行转换。
+ `POST` 方法将允许用户使用映射模板将宠物信息 `POST` 到 Amazon DynamoDB 表中。

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/data-transformation-tutorial-console.zip)。您将使用此模板创建 DynamoDB 表来发布宠物信息和不完整的 API。您将在 API Gateway 控制台中完成其余步骤。

**创建 CloudFormation 堆栈**

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

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

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

1. 选择您下载的模板。

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

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

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

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

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

CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。当 CloudFormation 堆栈的状态为 **CREATE\$1COMPLETE** 时，您就可以继续下一步了。

**测试 `GET` 集成响应**

1. 在 **data-transformation-tutorial-console** 的 CloudFormation 堆栈的**资源**选项卡上，选择您的 API 的物理 ID。

1. 在主导航窗格中，选择**资源**，然后选择 **GET** 方法。

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

   测试的输出将显示以下内容：

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

   您将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板转换此输出。

**转换 `GET` 集成响应**

1. 选择**集成响应**选项卡。

   目前，没有定义任何映射模板，因此不会转换集成响应。

1. 对于**默认 - 响应**，选择**编辑**。

1. 选择**映射模板**，然后执行以下操作：

   1. 选择**添加映射模板**。

   1. 对于**内容类型**，输入 **application/json**。

   1. 对于**模板正文**，输入以下内容：

      ```
      #set($inputRoot = $input.path('$'))
      [
      #foreach($elem in $inputRoot)
        {
          "description" : "Item $elem.id is a $elem.type.",
          "askingPrice" : $elem.price
        }#if($foreach.hasNext),#end
      
      #end
      ]
      ```

   选择**保存**。

**测试 `GET` 集成响应**
+ 选择**测试**选项卡，然后选择**测试**。

  测试的输出将显示转换后的响应。

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**转换来自 `POST` 方法的输入数据**

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

1. 选择**集成请求**选项卡，然后对于**集成请求设置**，选择**编辑**。

   CloudFormation 模板已填充了一些集成请求字段。
   +  集成类型为 AWS 服务。
   +  AWS 服务是 DynamoDB。
   +  HTTP 方法为 `POST`。
   +  操作是 `PutItem`。
   +  允许 API Gateway 将项目放入 DynamoDB 表的执行角色是 `data-transformation-tutorial-console-APIGatewayRole`。CloudFormation 创建此角色以允许 API Gateway 拥有与 DynamoDB 交互的最低权限。

    尚未指定 DynamoDB 表的名称。您将在以下步骤中指定名称。

1. 对于**请求正文传递**，选择**从不**。

   这意味着 API 将拒绝其 Content-Type（内容类型）没有映射模板的数据。

1. 选择**映射模板**。

1. **内容类型**设置为 `application/json`。这意味着 API 将拒绝所有不是 application/json 的内容类型。有关集成传递行为的更多信息，请参阅[API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)

1. 在文本编辑器中输入以下代码。

   ```
   {
       "TableName":"data-transformation-tutorial-console-ddb",
       "Item": {
           "id": {
               "N": $input.json("$.id")
           },
           "type": {
               "S": $input.json("$.type")
           },
           "price": {
               "N": $input.json("$.price")
           }
       }
   }
   ```

    此模板将表指定为 `data-transformation-tutorial-console-ddb` 并将项目设置为 `id`、`type` 和 `price`。这些项目将来自 `POST` 方法的正文。您也可以使用数据模型来帮助创建映射模板。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 的请求验证](api-gateway-method-request-validation.md)。

1. 选择**保存**以保存映射模板。

**从 `POST` 方法添加方法和集成响应**

CloudFormation 创建了一个空白方法和集成响应。您将编辑此回复以提供更多信息。有关如何编辑响应的更多信息，请参阅[API Gateway 中 REST API 的参数映射示例](request-response-data-mappings.md)。

1. 在**集成响应**选项卡上，对于**默认 - 响应**，选择**编辑**。

1. 选择**映射模板**，然后选择**添加映射模板**。

1. 对于 **Content-Type**，输入 **application/json**。

1. 在代码编辑器中，输入以下输出映射模板以发送输出消息：

   ```
   { "message" : "Your response was recorded at $context.requestTime" }
   ```

   有关上下文变量的更多信息，请参阅[数据转换的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)。

1. 选择**保存**以保存映射模板。

**测试 `POST` 方法**

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

1. 在请求正文中，输入以下示例。

   ```
   {
             "id": "4",
             "type" : "dog",
             "price": "321"
   }
   ```

1. 选择**测试**。

   输出应显示您的成功消息。

    您可以通过 [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/) 打开 DynamoDB 控制台，以验证示例项目是否在您的表中。

**删除 CloudFormation 堆栈**

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

1. 选择您的 CloudFormation 堆栈。

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

## 使用 AWS CLI 设置数据转换
<a name="mapping-example-cli"></a>

在本教程中，您将使用以下 .zip 文件 [data-transformation-tutorial-cli.zip](samples/data-transformation-tutorial-cli.zip) 创建不完整的 API 和 DynamoDB 表。这个不完整的 API 所具有的 `/pets` 资源包含与 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点集成的 `GET` 方法。您将创建 `POST` 方法以连接到 DynamoDB 表，并使用映射模板将数据输入到 DynamoDB 表中。
+ 您将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板转换输出数据。
+ 您将创建 `POST` 方法，以允许用户使用映射模板将宠物信息 `POST` 到 Amazon DynamoDB 表中。

**创建 CloudFormation 堆栈**

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/data-transformation-tutorial-cli.zip)。

要完成以下教程，您需要 [AWS Command Line Interface（AWS CLI）版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

对于长命令，使用转义字符 (`\`) 将命令拆分为多行。
**注意**  
在 Windows 中，操作系统的内置终端不支持您经常使用的某些 Bash CLI 命令（例如 `zip`）。[安装 Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install)，获取 Ubuntu 和 Bash 与 Windows 集成的版本。本指南中的示例 CLI 命令使用 Linux 格式。如果您使用的是 Windows CLI，则必须重新格式化包含内联 JSON 文档的命令。

1.  输入以下命令创建 CloudFormation 堆栈。

   ```
   aws cloudformation create-stack --stack-name data-transformation-tutorial-cli --template-body file://data-transformation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。使用以下命令查看 CloudFormation 的状态。

   ```
   aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli
   ```

1. 当 CloudFormation 堆栈的状态为 `StackStatus: "CREATE_COMPLETE"` 时，使用以下命令检索将来步骤的相关输出值。

   ```
    aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   输出值包括：
   + ApiRole，这是允许 API Gateway 在 DynamoDB 表中放置项目的角色名称。对于本教程，角色名称为 `data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG`。
   + DDBTableName，这是 DynamoDB 表的名称。对于本教程，表名称为 `data-transformation-tutorial-cli-ddb`
   + ResourceId，这是公开 `GET` 和 `POST` 方法的宠物资源的 ID。对于本教程，资源 ID 为 `efg456`
   + ApiId，这是 API 的 ID。对于本教程，API ID 为 `abc123`。

**在数据转换之前测试 `GET` 方法**
+ 使用以下命令测试 `GET` 方法。

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
            --resource-id efg456 \
            --http-method GET
  ```

  测试的输出将显示以下内容。

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

  您将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板转换此输出。

**转换 `GET` 集成响应**
+ 使用以下命令更新 `GET` 方法的集成响应。将 *rest-api-id* 和 *resource-id* 替换为您的值。

  使用以下命令创建集成响应。

  ```
  aws apigateway put-integration-response --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
    --status-code 200 \
    --selection-pattern "" \
    --response-templates '{"application/json": "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"}'
  ```

**测试 `GET` 方法**
+ 使用以下命令测试 `GET` 方法。

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
  ```

  测试的输出将显示转换后的响应。

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**创建 `POST` 方法**

1. 使用以下命令在您的 `/pets` 资源上创建新的方法。

   ```
   aws apigateway put-method --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --authorization-type "NONE" \
   ```

   此方法允许您将宠物信息发送到您在 CloudFormation 堆栈中创建的 DynamoDB 表。

1.  使用以下命令在 `POST` 方法上创建 AWS 服务 集成。

   ```
   aws apigateway put-integration --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --type AWS \
     --integration-http-method POST \
     --uri "arn:aws:apigateway:us-east-2:dynamodb:action/PutItem" \
     --credentials arn:aws:iam::111122223333:role/data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG \
     --request-templates '{"application/json":"{\"TableName\":\"data-transformation-tutorial-cli-ddb\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"}'
   ```

1.  使用以下命令为成功调用 `POST` 方法创建方法响应。

   ```
   aws apigateway put-method-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200
   ```

1. 使用以下命令为成功调用 `POST` 方法创建集成响应。

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200 \
     --selection-pattern "" \
     --response-templates '{"application/json": "{\"message\": \"Your response was recorded at $context.requestTime\"}"}'
   ```

**测试 `POST` 方法**
+ 使用以下命令测试 `POST` 方法。

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method POST \
    --body '{\"id\": \"4\", \"type\": \"dog\", \"price\": \"321\"}'
  ```

  输出将显示成功消息。

**删除 CloudFormation 堆栈**
+ 使用以下命令删除您的 CloudFormation 资源。

  ```
  aws cloudformation delete-stack  --stack-name data-transformation-tutorial-cli
  ```

## 已完成的数据转换 CloudFormation 模板
<a name="api-gateway-data-transformations-full-cfn-stack"></a>

以下示例是一个已完成的 CloudFormation 模板，它创建了一个 API 和一个 DynamoDB 表，该表的 `/pets` 资源具有 `GET` 和 `POST` 方法。
+ `GET` 方法将从 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点获取数据。输出数据将根据[API Gateway 中 REST API 的映射模板转换](models-mappings.md)中的映射模板进行转换。
+ `POST` 方法将允许用户使用映射模板将宠物信息 `POST` 到 DynamoDB 表中。

### 示例 CloudFormation 模板
<a name="mapping-template-cfn-example"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A completed Amazon API Gateway REST API that uses non-proxy integration to POST to an Amazon DynamoDB table and non-proxy integration to GET transformed pets data.
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  DynamoDBTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !Sub data-transformation-tutorial-complete
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: N
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  APIGatewayRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: APIGatewayDynamoDBPolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:PutItem'
                Resource: !GetAtt DynamoDBTable.Arn
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: data-transformation-complete-api
      ApiKeySourceType: HEADER
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: HTTP
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
        PassthroughBehavior: WHEN_NO_TEMPLATES
        IntegrationResponses:
          - StatusCode: '200'
            ResponseTemplates:
              application/json: "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"
      MethodResponses:
        - StatusCode: '200'
  PetsMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: POST
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: POST
        Uri: arn:aws:apigateway:us-west-1:dynamodb:action/PutItem
        PassthroughBehavior: NEVER
        RequestTemplates: 
          application/json: "{\"TableName\":\"data-transformation-tutorial-complete\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: "{\"message\": \"Your response was recorded at $context.requestTime\"}"
      MethodResponses:
        - StatusCode: '200'

  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiId:
    Description: API ID for CLI commands
    Value: !Ref Api
  ResourceId:
    Description: /pets resource ID for CLI commands
    Value: !Ref PetsResource
  ApiRole:
    Description: Role ID to allow API Gateway to put and scan items in DynamoDB table
    Value: !Ref APIGatewayRole
  DDBTableName:
    Description: DynamoDB table name
    Value: !Ref DynamoDBTable
```

# 使用变量来映射 API Gateway 的模板转换的示例
<a name="api-gateway-mapping-variable-examples"></a>

以下示例显示了如何在映射模板中使用 `$context`、`input` 和 `util` 变量。您可以使用模拟集成或用于将输入事件返回到 API Gateway 的 Lambda 非代理集成。有关数据转换的所有支持的变量的列表，请参阅 [API Gateway 的用于数据转换的变量](api-gateway-mapping-template-reference.md)。

## 示例 1：将多个 `$context` 变量传递到集成端点
<a name="context-variables-template-example"></a>

以下示例显示了一个映射模板，该模板将传入的 `$context` 变量映射到后端变量，这些变量在集成请求负载中的名称稍有不同：

```
{
    "stage" : "$context.stage",
    "request_id" : "$context.requestId",
    "api_id" : "$context.apiId",
    "resource_path" : "$context.resourcePath",
    "resource_id" : "$context.resourceId",
    "http_method" : "$context.httpMethod",
    "source_ip" : "$context.identity.sourceIp",
    "user-agent" : "$context.identity.userAgent",
    "account_id" : "$context.identity.accountId",
    "api_key" : "$context.identity.apiKey",
    "caller" : "$context.identity.caller",
    "user" : "$context.identity.user",
    "user_arn" : "$context.identity.userArn"
}
```

此映射模板的输出应与以下内容类似：

```
{
  stage: 'prod',
  request_id: 'abcdefg-000-000-0000-abcdefg',
  api_id: 'abcd1234',
  resource_path: '/',
  resource_id: 'efg567',
  http_method: 'GET',
  source_ip: '192.0.2.1',
  user-agent: 'curl/7.84.0',
  account_id: '111122223333',
  api_key: 'MyTestKey',
  caller: 'ABCD-0000-12345',
  user: 'ABCD-0000-12345',
  user_arn: 'arn:aws:sts::111122223333:assumed-role/Admin/carlos-salazar'
}
```

其中一个变量是 API 密钥。此示例假设方法需要 API 密钥。

## 示例 2：通过 JSON 有效载荷将所有请求参数传递给集成端点
<a name="input-examples-mapping-templates"></a>

以下示例通过 JSON 有效载荷将所有请求参数（包括 `path`、`querystring` 和 `header` 参数）传递到集成端点：

```
#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}
```

如果请求具有以下输入参数：
+ 名为 `myparam` 的路径参数
+ 查询字符串参数 `querystring1=value1,value2`
+ 标头 `"header1" : "value1"`。

此映射模板的输出应与以下内容类似：

```
{"params":{"path":{"example2":"myparamm"},"querystring":{"querystring1":"value1,value2"},"header":{"header1":"value1"}}}
```

## 示例 3：将方法请求的一部分传递给集成端点
<a name="input-example-json-mapping-template"></a>

 以下示例使用输入参数 `name` 仅检索 `name` 参数，并使用输入参数 `input.json('$')` 检索方法请求的整个正文：

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$') 
}
```

对于包含查询字符串参数 `name=Bella&type=dog` 和以下正文的请求：

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body" : {"Price":"249.99","Age":"6"}
}
```

此映射模板移除了查询字符串参数 `type=dog`。

 如果 JSON 输入包含无法通过 JavaScript 解析的非转义字符，则 API Gateway 可能会返回 400 响应。应用 `$util.escapeJavaScript($input.json('$'))` 来确保正确解析 JSON 输入。

上面的示例在应用了 `$util.escapeJavaScript($input.json('$'))` 之后会如下所示：

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$'))"
}
```

在这种情况下，此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body": {"Price":"249.99","Age":"6"}
}
```

## 示例 4：使用 JSONPath 表达式将方法请求的一部分传递给集成端点
<a name="input-example-inputs-mapping-template"></a>

以下示例使用 JSONPath 表达式从请求正文中仅检索输入参数 `name` 和 `Age`：

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$.Age')  
}
```

对于包含查询字符串参数 `name=Bella&type=dog` 和以下正文的请求：

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body" : "6"
}
```

此映射模板从正文中移除查询字符串参数 `type=dog` 和 `Price` 字段。

 如果方法请求负载包含无法通过 JavaScript 解析的非转义字符，则 API Gateway 可能会返回 `400` 响应。应用 `$util.escapeJavaScript()` 来确保正确解析 JSON 输入。

上面的示例在应用了 `$util.escapeJavaScript($input.json('$.Age'))` 之后会如下所示：

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$.Age'))" 
}
```

在这种情况下，此映射模板的输出应与以下内容类似：

```
{
    "name" : "Bella",
    "body": "\"6\""
}
```

## 示例 5：使用 JSONPath 表达式将有关方法请求的信息传递到集成端点
<a name="input-example-request-and-response"></a>

以下示例使用 `$input.params()`、`$input.path()` 和 `$input.json()` 向集成端点发送有关方法请求的信息。此映射模板使用 `size()` 方法来提供列表中元素的数量。

```
{
    "id" : "$input.params('id')",
    "count" : "$input.path('$.things').size()",
    "things" : $input.json('$.things')
}
```

对于包含路径参数 `123` 和以下正文的请求：

```
{
      "things": {
            "1": {},
            "2": {},
            "3": {}
      }
}
```

此映射模板的输出应与以下内容类似：

```
{"id":"123","count":"3","things":{"1":{},"2":{},"3":{}}}
```

 如果方法请求负载包含无法通过 JavaScript 解析的非转义字符，则 API Gateway 可能会返回 `400` 响应。应用 `$util.escapeJavaScript()` 来确保正确解析 JSON 输入。

上面的示例在应用了 `$util.escapeJavaScript($input.json('$.things'))` 之后会如下所示：

```
{
     "id" : "$input.params('id')",
     "count" : "$input.path('$.things').size()",
     "things" : "$util.escapeJavaScript($input.json('$.things'))"
}
```

此映射模板的输出应与以下内容类似：

```
{"id":"123","count":"3","things":"{\"1\":{},\"2\":{},\"3\":{}}"}
```

# API Gateway 的用于数据转换的变量
<a name="api-gateway-mapping-template-reference"></a>

创建参数映射时，可以使用上下文变量作为数据来源。创建映射模板转换时，可以在用 [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) 编写的脚本中使用上下文变量、输入和 util 变量。有关使用这些参考变量的映射模板的示例，请参阅[使用变量来映射 API Gateway 的模板转换的示例](api-gateway-mapping-variable-examples.md)。

有关访问日志记录的参考变量的列表，请参阅 [API Gateway 的访问日志记录的变量](api-gateway-variables-for-access-logging.md)。

## 数据转换的上下文变量
<a name="context-variable-reference"></a>

可以使用以下区分大小写的 `$context` 变量来进行数据转换。


| 参数 | 说明 | 
| --- | --- | 
| \$1context.accountId |  API 拥有者的 AWS 账户 ID。  | 
| \$1context.apiId |  API Gateway 分配给您的 API 的标识符。  | 
| \$1context.authorizer.claims.property |  成功对方法调用方进行身份验证后从 Amazon Cognito 用户池返回的声明的属性。有关更多信息，请参阅 [使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问](apigateway-integrate-with-cognito.md)。  调用 `$context.authorizer.claims` 将返回 null。   | 
| \$1context.authorizer.principalId |  与由客户端发送的令牌关联并从 API Gateway Lambda 授权方（以前称为自定义授权方）返回的委托人用户标识。有关更多信息，请参阅 [使用 API Gateway Lambda 授权方](apigateway-use-lambda-authorizer.md)。  | 
| \$1context.authorizer.property |  从 API Gateway Lambda 授权方函数返回的 `context` 映射的指定键/值对的字符串化值。例如，如果授权方返回以下 `context` 映射： <pre>"context" : {<br />  "key": "value",<br />  "numKey": 1,<br />  "boolKey": true<br />}</pre> 调用 `$context.authorizer.key` 将返回 `"value"` 字符串，调用 `$context.authorizer.numKey` 将返回 `"1"` 字符串，而调用 `$context.authorizer.boolKey` 将返回 `"true"` 字符串。 对于*属性*，唯一支持的特殊字符是下划线 `(_)` 字符。 有关更多信息，请参阅 [使用 API Gateway Lambda 授权方](apigateway-use-lambda-authorizer.md)。  | 
| \$1context.awsEndpointRequestId |  AWS 端点的请求 ID。  | 
| \$1context.deploymentId | API 部署的 ID。 | 
| \$1context.domainName |  用于调用 API 的完整域名。这应与传入的 `Host` 标头相同。  | 
| \$1context.domainPrefix |  `$context.domainName` 的第一个标签。  | 
| \$1context.error.message |  包含 API Gateway 错误消息的字符串。此变量只能用于 [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) 正文映射模板中（不由 Velocity 模板语言引擎处理）和访问日志记录中的简单变量替换。有关更多信息，请参阅 [使用 CloudWatch 指标监控 WebSocket API 执行](apigateway-websocket-api-logging.md) 和 [设置网关响应以自定义错误响应](api-gateway-gatewayResponse-definition.md#customize-gateway-responses)。  | 
| \$1context.error.messageString | \$1context.error.message 的带引号的值，即 "\$1context.error.message"。 | 
| \$1context.error.responseType |  [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) 的[类型](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseType) 此变量只能用于 [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) 正文映射模板中（不由 Velocity 模板语言引擎处理）和访问日志记录中的简单变量替换。有关更多信息，请参阅 [使用 CloudWatch 指标监控 WebSocket API 执行](apigateway-websocket-api-logging.md) 和 [设置网关响应以自定义错误响应](api-gateway-gatewayResponse-definition.md#customize-gateway-responses)。  | 
| \$1context.error.validationErrorString |  包含详细验证错误消息的字符串。  | 
| \$1context.extendedRequestId | API Gateway 生成并分配给 API 请求的扩展 ID。扩展请求 ID 包含调试和故障排除的有用信息。 | 
| \$1context.httpMethod |  所用的 HTTP 方法。有效值包括：`DELETE`、`GET`、`HEAD`、`OPTIONS`、`PATCH`、`POST` 和 `PUT`。  | 
| \$1context.identity.accountId |  与请求关联的 AWS 账户 ID。  | 
| \$1context.identity.apiKey |  对于需要 API 密钥的 API 方法，此变量是与该方法请求关联的 API 密钥。对于无需 API 密钥的方法，此变量为 null。有关更多信息，请参阅 [API Gateway 中针对 REST API 的使用计划和 API 密钥](api-gateway-api-usage-plans.md)。  | 
| \$1context.identity.apiKeyId | 与需要 API 密钥的 API 请求关联的 API 密钥 ID。 | 
| \$1context.identity.caller |  签发请求的调用方的委托人标识符。对于使用 IAM 授权的资源支持此项。  | 
| \$1context.identity.cognitoAuthenticationProvider |  发出请求的调用方使用的所有 Amazon Cognito 身份验证提供商的逗号分隔列表。仅当使用 Amazon Cognito 凭证对请求签名时才可用。 例如，对于 Amazon Cognito 身份池中的身份，`cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` 有关更多信息，请参阅 *Amazon Cognito 开发人员指南* 中的[使用联合身份](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)。 | 
| \$1context.identity.cognitoAuthenticationType |  发出请求的调用方的 Amazon Cognito 身份验证类型。仅当使用 Amazon Cognito 凭证对请求签名时才可用。可能的值包括经过身份验证的身份的 `authenticated` 和未经身份验证的身份的 `unauthenticated`。 | 
| \$1context.identity.cognitoIdentityId |  发出请求的调用方的 Amazon Cognito 身份 ID。仅当使用 Amazon Cognito 凭证对请求签名时才可用。  | 
| \$1context.identity.cognitoIdentityPoolId |  发出请求的调用方的 Amazon Cognito 身份池 ID。仅当使用 Amazon Cognito 凭证对请求签名时才可用。  | 
| \$1context.identity.principalOrgId |  [AWS 组织 ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html)。  | 
| \$1context.identity.sourceIp |  向 API Gateway 端点发出请求的即时 TCP 连接的源 IP 地址。  | 
| \$1context.identity.clientCert.clientCertPem |  客户端在双向 TLS 身份验证过程中提供的 PEM 编码的客户端证书。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。仅在双向 TLS 身份验证失败时才出现在访问日志中。  | 
| \$1context.identity.clientCert.subjectDN |  客户端提供的证书的主题的可分辨名称。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。仅在双向 TLS 身份验证失败时才出现在访问日志中。  | 
| \$1context.identity.clientCert.issuerDN |  客户端提供的证书的颁发者的可分辨名称。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。仅在双向 TLS 身份验证失败时才出现在访问日志中。  | 
| \$1context.identity.clientCert.serialNumber |  证书的序列号。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。仅在双向 TLS 身份验证失败时才出现在访问日志中。  | 
| \$1context.identity.clientCert.validity.notBefore |  证书无效之前的日期。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。仅在双向 TLS 身份验证失败时才出现在访问日志中。  | 
| \$1context.identity.clientCert.validity.notAfter |  证书无效后的日期。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。仅在双向 TLS 身份验证失败时才出现在访问日志中。  | 
|  \$1context.identity.vpcId | 向 API Gateway 端点发出请求的 VPC 的 VPC ID。 | 
|  \$1context.identity.vpceId |  向 API Gateway 端点发出请求的 VPC 端点的 VPC 端点 ID。仅当您具有私有 API 时才会显示。  | 
| \$1context.identity.user |  将获得资源访问权限授权的用户的委托人标识符。对于使用 IAM 授权的资源支持此项。  | 
| \$1context.identity.userAgent |  API 调用方的 [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) 标头。  | 
| \$1context.identity.userArn |  身份验证后标识的有效用户的 Amazon Resource Name (ARN)。有关更多信息，请参阅 [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)。  | 
| \$1context.isCanaryRequest |  如果请求定向到金丝雀，将返回 `true`，如果请求没有定向到金丝雀，将返回 `false`。仅当您启用金丝雀时才会显示。 | 
| \$1context.path | 请求路径。例如，对于 https://\$1rest-api-id\$1.execute-api.\$1region\$1.amazonaws.com/\$1stage\$1/root/child 的非代理请求 URL，\$1context.path 值为 /\$1stage\$1/root/child。 | 
| \$1context.protocol | 请求的协议，例如，HTTP/1.1。 API Gateway API 可以接受 HTTP/2 请求，但 API Gateway 使用 HTTP/1.1 向后端集成发送请求。因此，即使客户端发送的请求使用 HTTP/2，请求协议也会记录为 HTTP/1.1。   | 
| \$1context.requestId |  请求的 ID。客户可以覆盖此请求 ID。使用 `$context.extendedRequestId` 用于 API Gateway 生成的唯一请求 ID。  | 
| \$1context.requestOverride.header.header\$1name |  请求标头覆盖。如果定义此参数，则它将包含要使用的标题，而不是**集成请求**窗格中定义的 **HTTP 标头**。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。  | 
| \$1context.requestOverride.path.path\$1name |  请求路径覆盖。如果定义此参数，则它将包含要使用的请求路径，而不是**集成请求**窗格中定义的 **URL 路径参数**。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。  | 
| \$1context.requestOverride.querystring.querystring\$1name |  请求查询字符串覆盖。如果定义此参数，则它将包含要使用的请求查询字符串，而不是**集成请求**窗格中定义的 **URL 查询字符串参数**。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。  | 
| \$1context.responseOverride.header.header\$1name | 响应标头覆盖。如果定义此参数，则它包含要使用的标头，而不是集成响应窗格中定义为默认映射的响应标头。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。 | 
| \$1context.responseOverride.status | 响应状态代码覆盖。如果定义此参数，则它包含要使用的状态代码，而不是集成响应窗格中定义为默认映射的方法响应状态。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 覆盖 API 的请求和响应参数以及状态代码](apigateway-override-request-response-parameters.md)。 | 
| \$1context.requestTime | [CLF](https://httpd.apache.org/docs/current/logs.html#common) 格式的请求时间 (dd/MMM/yyyy:HH:mm:ss \$1-hhmm)。 | 
| \$1context.requestTimeEpoch | [Epoch](https://en.wikipedia.org/wiki/Unix_time) 格式的请求时间，以毫秒为单位。 | 
| \$1context.resourceId |  API Gateway 分配给您的资源的标识符。  | 
| \$1context.resourcePath |  资源路径。例如，对于 `https://{rest-api-id}.execute-api.{region}.amazonaws.com/{stage}/root/child` 的非代理请求 URI，`$context.resourcePath` 值为 `/root/child`。有关更多信息，请参阅 [教程：使用 HTTP 非代理集成创建 REST API](api-gateway-create-api-step-by-step.md)。  | 
| \$1context.stage |  API 请求的部署阶段（例如，`Beta` 或 `Prod`）。  | 
| \$1context.wafResponseCode |  从 [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) 中收到的响应：`WAF_ALLOW` 或 `WAF_BLOCK`。如果阶段未与 Web ACL 关联，则不会设置。有关更多信息，请参阅 [在 API Gateway 中使用 AWS WAF 保护 REST API](apigateway-control-access-aws-waf.md)。  | 
| \$1context.webaclArn |  Web ACL 的完整 ARN，用于决定是允许还是阻止请求。如果阶段未与 Web ACL 关联，则不会设置。有关更多信息，请参阅 [在 API Gateway 中使用 AWS WAF 保护 REST API](apigateway-control-access-aws-waf.md)。  | 

## 输入变量
<a name="input-variable-reference"></a>

可以使用以下区分大小写的 `$input` 变量来引用方法请求有效载荷和方法请求参数。可以执行以下功能：


| 变量和函数 | 说明 | 
| --- | --- | 
| \$1input.body |  以字符串形式返回原始请求负载。您可以使用 `$input.body` 来保留整个浮点数，例如 `10.00`。 | 
| \$1input.json(x) | 此函数计算 JSONPath 表达式并以 JSON 字符串形式返回结果。 例如，`$input.json('$.pets')` 返回一个表示 `pets` 结构的 JSON 字符串。 有关 JSONPath 的更多信息，请参阅 [JSONPath](https://goessner.net/articles/JsonPath/) 或[适用于 Java 的 JSONPath](https://github.com/json-path/JsonPath)。 | 
| \$1input.params() |  返回所有请求参数的映射。我们建议您使用 `$util.escapeJavaScript` 对结果进行清理，以避免潜在的注入攻击。要完全控制请求清理，可以使用没有模板的代理集成，并在集成中处理请求清理。 | 
| \$1input.params(x) | 在给定参数名称字符串 `x` 的情况下，返回路径中的方法请求参数值、查询字符串或标头值（按照该顺序搜索）。我们建议您使用 `$util.escapeJavaScript` 对参数进行清理，以避免潜在的注入攻击。要完全控制参数清理，可以使用没有模板的代理集成，并在集成中处理请求清理。 | 
| \$1input.path(x) | 获取一个 JSONPath 表达式字符串 (`x`) 并返回结果的 JSON 对象表达式。这样，您便可通过 [Apache Velocity 模板语言 (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) 在本机访问和操作负载的元素。 例如，如果表达式 `$input.path('$.pets')` 返回一个如下所示的对象： <pre>[<br />  { <br />    "id": 1, <br />    "type": "dog", <br />    "price": 249.99 <br />  }, <br />  { <br />    "id": 2, <br />    "type": "cat", <br />    "price": 124.99 <br />  }, <br />  { <br />    "id": 3, <br />    "type": "fish", <br />    "price": 0.99 <br />  } <br />]</pre> `$input.path('$.pets').size()` 将返回 `"3"`。 有关 JSONPath 的更多信息，请参阅 [JSONPath](https://goessner.net/articles/JsonPath/) 或[适用于 Java 的 JSONPath](https://github.com/json-path/JsonPath)。 | 

## 阶段变量
<a name="stagevariables-template-reference"></a>

在方法集成中，可以使用以下阶段变量作为 ARN 和 URL 的占位符。有关更多信息，请参阅 [在 API Gateway 中对 REST API 使用阶段变量](stage-variables.md)。


| 语法 | 说明 | 
| --- | --- | 
| \$1stageVariables.variable\$1name、\$1stageVariables['variable\$1name'] 或 \$1\$1stageVariables['variable\$1name']\$1  |  *variable\$1name* 表示阶段变量名称。  | 

## Util 变量
<a name="util-template-reference"></a>

您可以使用以下区分大小写的 `$util` 变量，以便将实用程序函数用于映射模板。除非另行指定，否则默认字符集为 UTF-8。


| 函数 | 说明 | 
| --- | --- | 
| \$1util.escapeJavaScript() |  使用 JavaScript 字符串规则对字符串中的字符进行转义。  此函数会将任何常规单引号 (`'`) 变成转义单引号 (`\'`)。但是，转义单引号在 JSON 中无效。因此，当此函数的输出用于 JSON 属性时，必须将任何转义单引号 (`\'`) 变回常规单引号 (`'`)。如下例所示:  <pre> "input" : "$util.escapeJavaScript(data).replaceAll("\\'","'")"</pre>   | 
| \$1util.parseJson() |   获取“字符串化的”JSON 并返回结果的对象表示形式。您可以使用此函数的结果通过 Apache Velocity 模板语言 (VTL) 在本机访问和操作负载的元素。例如，如果您具有以下负载： <pre>{"errorMessage":"{\"key1\":\"var1\",\"key2\":{\"arr\":[1,2,3]}}"}</pre>  并使用以下映射模板  <pre>#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))<br />{<br />   "errorMessageObjKey2ArrVal" : $errorMessageObj.key2.arr[0]<br />}<br /></pre> 您将得到以下输出： <pre>{<br />   "errorMessageObjKey2ArrVal" : 1<br />}<br /></pre>  | 
| \$1util.urlEncode() | 将字符串转换为“application/x-www-form-urlencoded”格式。 | 
| \$1util.urlDecode() | 对“application/x-www-form-urlencoded”字符串进行解码。 | 
| \$1util.base64Encode() | 将数据编码为 base64 编码的字符串。 | 
| \$1util.base64Decode() | 对 base64 编码字符串中的数据进行解码。 | 

# 针对 API Gateway 中 REST API 的网关响应
<a name="api-gateway-gatewayResponse-definition"></a>

 网关响应使用 API Gateway 定义的响应类型进行标识。响应由 HTTP 状态代码（这是一组由参数映射指定的额外标头）和由非 [VTL](https://velocity.apache.org/engine/devel/vtl-reference.html) 映射模板生成的有效载荷组成。

 在 API Gateway REST API 中，[GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) 表示网关响应。在 OpenAPI 中，[x-amazon-apigateway-gateway-responses.gatewayResponse](api-gateway-swagger-extensions-gateway-responses.gatewayResponse.md) 扩展表示 `GatewayResponse` 实例。

要启用网关响应，您需要在 API 级别为[受支持的响应类型](supported-gateway-response-types.md)设置网关响应。每当 API Gateway 返回该类型的响应时，都将使用在网关响应中定义的标头映射和负载映射模板，以将映射结果返回 API 调用方。

 下一节我们将介绍如何使用 API Gateway 控制台和 API Gateway REST API 设置网关响应。

## 设置网关响应以自定义错误响应
<a name="customize-gateway-responses"></a>

如果 API Gateway 无法处理某个传入请求，它会向客户端返回一个错误响应，而不会将请求转发到集成后端。默认情况下，错误响应会包含一个简短的描述性错误消息。例如，如果您尝试对未定义的 API 资源调用操作，您将收到一个显示 `{ "message": "Missing Authentication Token" }` 消息的错误响应。如果首次使用 API Gateway，您可能会发现很难找到真正的问题。

 对于某些错误响应，API Gateway 允许 API 开发人员通过自定义返回不同格式的响应。对于 `Missing Authentication Token` 示例，您可以为原始响应负载添加提示标注可能的原因，如下例所示：`{"message":"Missing Authentication Token", "hint":"The HTTP method or resources may not be supported."}`。

 当您的 API 在外部交换和 AWS 云之间提供协调时，您可以使用集成请求或集成响应的 VTL 映射模板将负载从一种格式映射到另一种格式。但是，VTL 映射模板仅适用于能够成功响应的有效请求。

对于无效请求，API Gateway 可以完全绕过该集成，返回错误响应。您必须通过自定义，以可支持交换的格式发出错误响应。此时，使用仅支持简单变量替换的非 VTL 映射模板进行自定义。

 将 API Gateway 生成的错误响应泛化处理成由 API Gateway 生成的任何响应，我们将它们称为*网关响应*。以此区分 API Gateway 生成的响应与集成响应。网关响应映射模板能以 `$context` 的形式访问 `$stageVariables` 变量值和 `method.request.param-position.param-name` 属性值以及方法请求参数。

有关 `$context` 变量的更多信息，请参阅 [数据转换的上下文变量](api-gateway-mapping-template-reference.md#context-variable-reference)。有关 `$stageVariables` 的更多信息，请参阅 [阶段变量](api-gateway-mapping-template-reference.md#stagevariables-template-reference)。有关方法请求参数的更多信息，请参阅 [输入变量](api-gateway-mapping-template-reference.md#input-variable-reference)。

**Topics**
+ [设置网关响应以自定义错误响应](#customize-gateway-responses)
+ [使用 API Gateway 控制台为 REST API 设置网关响应](set-up-gateway-response-using-the-console.md)
+ [使用 API Gateway REST API 设置网关响应](set-up-gateway-response-using-the-api.md)
+ [在 OpenAPI 中设置网关响应自定义](set-up-gateway-responses-in-swagger.md)
+ [API Gateway 的网关响应类型](supported-gateway-response-types.md)

# 使用 API Gateway 控制台为 REST API 设置网关响应
<a name="set-up-gateway-response-using-the-console"></a>

以下示例说明如何使用 API Gateway 控制台为 REST API 设置网关响应 

**使用 API Gateway 控制台自定义网关响应**

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

1. 选择一个 REST API。

1. 在主导航窗格中，选择**网关响应**。

1. 选择响应类型，然后选择**编辑**。在本次演练中，我们将以**缺少身份验证令牌**为例。

1. 您可以更改 API Gateway 生成的**状态代码**，以返回满足您的 API 要求的不同状态代码。在此示例中，自定义会将状态代码从默认值 (`403`) 更改为 `404`，因为在客户端调用可被视为未找到的不受支持或无效的资源时，会出现此错误消息。

1. 要返回自定义标头，请选择**响应标头**下的**添加响应标头**。为方便说明，我们将添加以下自定义标头：

   ```
   Access-Control-Allow-Origin:'a.b.c'
   x-request-id:method.request.header.x-amzn-RequestId
   x-request-path:method.request.path.petId
   x-request-query:method.request.querystring.q
   ```

   在前面的标头映射中，将静态域名 (`'a.b.c'`) 映射到 `Allow-Control-Allow-Origin` 标头以允许 CORS 访问 API；将 `x-amzn-RequestId` 的输入请求标头映射到响应中的 `request-id`；将传入请求的 `petId` 路径变量映射到响应中的 `request-path` 标头；以及将原始请求的 `q` 查询参数映射到响应的 `request-query` 标头。

1. 在**响应模板**下，将 `application/json` 保留为**内容类型**，然后在**模板正文**编辑器中输入以下正文映射模板：

   ```
   {
        "message":"$context.error.messageString",
        "type": "$context.error.responseType",
        "statusCode": "'404'",
        "stage": "$context.stage",
        "resourcePath": "$context.resourcePath",
        "stageVariables.a": "$stageVariables.a"
   }
   ```

   此示例显示了如何将 `$context` 和 `$stageVariables` 属性映射到网关响应正文的属性。

1. 选择**保存更改**。

1. 将 API 部署到新阶段或现有阶段。

通过调用以下 CURL 命令测试您的网关响应，假设相应 API 方法的调用 URL 是 `https://o81lxisefl.execute-api.us-east-1.amazonaws.com/custErr/pets/{petId}`：

```
curl -v -H 'x-amzn-RequestId:123344566' https://o81lxisefl.execute-api.us-east-1.amazonaws.com/custErr/pets/5/type?q=1
```

额外查询字符串参数 `q=1` 与 API 不兼容，因此指定的网关响应中返回了错误。您应收到与以下内容类似的网关响应：

```
> GET /custErr/pets/5?q=1 HTTP/1.1
Host: o81lxisefl.execute-api.us-east-1.amazonaws.com
User-Agent: curl/7.51.0
Accept: */*
 
HTTP/1.1 404 Not Found
Content-Type: application/json
Content-Length: 334
Connection: keep-alive
Date: Tue, 02 May 2017 03:15:47 GMT
x-amzn-RequestId: 123344566
Access-Control-Allow-Origin: a.b.c
x-amzn-ErrorType: MissingAuthenticationTokenException
header-1: static
x-request-query: 1
x-request-path: 5
X-Cache: Error from cloudfront
Via: 1.1 441811a054e8d055b893175754efd0c3.cloudfront.net (CloudFront)
X-Amz-Cf-Id: nNDR-fX4csbRoAgtQJ16u0rTDz9FZWT-Mk93KgoxnfzDlTUh3flmzA==
 
{
     "message":"Missing Authentication Token",
     "type": MISSING_AUTHENTICATION_TOKEN,
     "statusCode": '404',
     "stage": custErr,
     "resourcePath": /pets/{petId},
     "stageVariables.a": a
}
```

前面的示例假定 API 后端为 [Pet Store](http://petstore-demo-endpoint.execute-api.com/petstore/pets)，并且 API 有一个定义的阶段变量 `a`。

# 使用 API Gateway REST API 设置网关响应
<a name="set-up-gateway-response-using-the-api"></a>

 在使用 API Gateway REST API 自定义网关响应之前，您必须已创建 API 并获得其标识符。要检索 API 标识符，您可以使用 [restapi:gateway-responses](https://docs.aws.amazon.com/apigateway/latest/api/API_GetGatewayResponses.html) 链接关系并检查结果。

**使用 API Gateway REST API 自定义网关响应**

1. 要覆盖整个 [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) 实例，请调用 [gatewayresponse:put](https://docs.aws.amazon.com/apigateway/latest/api/API_PutGatewayResponse.html) 操作。在 URL 路径参数中指定所需的 [responseType](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseType)，并在请求负载中提供 [statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#statusCode)、[responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseParameters) 和 [responseTemplates](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseTemplates) 映射。

1. 要更新 `GatewayResponse` 实例的一部分，请调用 [gatewayresponse:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateGatewayResponse.html) 操作。在 URL 路径参数中指定所需的 `responseType`，并在请求中提供所需的单个 `GatewayResponse` 属性，例如，`responseParameters` 或 `responseTemplates` 映射。

# 在 OpenAPI 中设置网关响应自定义
<a name="set-up-gateway-responses-in-swagger"></a>

 在 OpenAPI 中，您可以在 API 根级别使用 `x-amazon-apigateway-gateway-responses` 扩展来自定义网关响应。下面的 OpenAPI 定义显示了自定义 `MISSING_AUTHENTICATION_TOKEN` 类型的 [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) 的示例。

```
  "x-amazon-apigateway-gateway-responses": {
    "MISSING_AUTHENTICATION_TOKEN": {
      "statusCode": 404,
      "responseParameters": {
        "gatewayresponse.header.x-request-path": "method.input.params.petId",
        "gatewayresponse.header.x-request-query": "method.input.params.q",
        "gatewayresponse.header.Access-Control-Allow-Origin": "'a.b.c'",
        "gatewayresponse.header.x-request-header": "method.input.params.Accept"
      },
      "responseTemplates": {
        "application/json": "{\n     \"message\": $context.error.messageString,\n     \"type\":  \"$context.error.responseType\",\n     \"stage\":  \"$context.stage\",\n     \"resourcePath\":  \"$context.resourcePath\",\n     \"stageVariables.a\":  \"$stageVariables.a\",\n     \"statusCode\": \"'404'\"\n}"
      }
    }
```

在此示例中，自定义设置将状态代码从默认 (`403`) 更改为 `404`。此外，它还会为网关响应添加了四个标头参数和一个 `application/json` 媒体类型的正文映射模板。

# API Gateway 的网关响应类型
<a name="supported-gateway-response-types"></a>

 API Gateway 公开了以下网关响应以供 API 开发人员进行自定义。


| 网关响应类型 | 默认状态代码 | 说明 | 
| --- | --- | --- | 
| ACCESS\$1DENIED | 403 | 授权失败的网关响应；例如，被自定义授权方或 Amazon Cognito 授权方拒绝访问时。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| API\$1CONFIGURATION\$1ERROR | 500 | 无效 API 配置的网关响应，包括提交无效的端点地址时，在设置二进制支持时对二进制数据进行 Base64 解码失败时，或者集成响应映射无法匹配任何模板且未配置默认模板时。如果未指定响应类型，则默认该响应为 `DEFAULT_5XX` 类型。 | 
| AUTHORIZER\$1CONFIGURATION\$1ERROR | 500 | 未能连接到自定义或 Amazon Cognito 授权方的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_5XX` 类型。 | 
| AUTHORIZER\$1FAILURE | 500 | 当自定义或 Amazon Cognito 授权方无法对调用方进行身份验证时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_5XX` 类型。 | 
| BAD\$1REQUEST\$1PARAMETERS | 400 | 当无法根据已启用的请求验证程序验证请求参数时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| BAD\$1REQUEST\$1BODY | 400 | 当无法根据已启用的请求验证程序验证请求正文时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| DEFAULT\$14XX |  Null | 状态代码为 `4XX` 的未指定响应类型的默认网关响应。更改此回退网关响应的状态代码会将所有其他 `4XX` 响应的状态代码更改为新值。将此状态代码重置为 Null 会使所有其他 `4XX` 响应的状态代码恢复到原始值。  [AWS WAF 自定义响应](https://docs.aws.amazon.com/waf/latest/developerguide/waf-custom-request-response.html)优先于自定义网关响应。   | 
| DEFAULT\$15XX | Null | 状态代码为 `5XX` 的未指定响应类型的默认网关响应。更改此回退网关响应的状态代码会将所有其他 `5XX` 响应的状态代码更改为新值。将此状态代码重置为 Null 会使所有其他 `5XX` 响应的状态代码恢复到原始值。 | 
| EXPIRED\$1TOKEN | 403 | 发生 AWS 身份验证令牌过期错误时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| INTEGRATION\$1FAILURE | 504 | 发生集成失败错误时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_5XX` 类型。 | 
| INTEGRATION\$1TIMEOUT | 504 | 发生集成超时错误时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_5XX` 类型。 | 
| INVALID\$1API\$1KEY | 403 | 为要求 API 密钥的方法提交无效 API 密钥时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| INVALID\$1SIGNATURE | 403 | 发生无效的 AWS 签名错误时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| MISSING\$1AUTHENTICATION\$1TOKEN | 403 | 发生缺少身份验证令牌错误时的网关响应，包括客户端尝试调用不受支持的 API 方法或资源的情况。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| QUOTA\$1EXCEEDED | 429 | 发生超出使用计划配额错误时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| REQUEST\$1TOO\$1LARGE | 413 | 发生请求太大错误时的网关响应。如果未指定响应类型，则该响应默认为：`HTTP content length exceeded 10485760 bytes`。 | 
| RESOURCE\$1NOT\$1FOUND | 404 | 在 API 请求通过身份验证和授权（不包括 API 密钥身份验证和授权）后，API Gateway 找不到指定资源时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| THROTTLED | 429 | 当超出使用计划、方法、阶段或账户的节流限制时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| UNAUTHORIZED | 401 | 当自定义或 Amazon Cognito 授权方无法对调用方进行身份验证时的网关响应。 | 
| UNSUPPORTED\$1MEDIA\$1TYPE | 415 | 当启用严格的传递限制后，负载为不受支持的媒体类型时的网关类型。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。 | 
| WAF\$1FILTERED | 403 | 当请求被 AWS WAF 阻止时的网关响应。如果未指定响应类型，则默认该响应为 `DEFAULT_4XX` 类型。  [AWS WAF 自定义响应](https://docs.aws.amazon.com/waf/latest/developerguide/waf-custom-request-response.html)优先于自定义网关响应。   | 

# 针对 API Gateway 中的 REST API 的 CORS
<a name="how-to-cors"></a>

[跨源资源共享 (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 是一项浏览器安全特征，该特征限制从在浏览器中运行的脚本启动的跨源 HTTP 请求。有关更多信息，请参阅[什么是 CORS？](https://aws.amazon.com/what-is/cross-origin-resource-sharing/)。

## 确定是否启用 CORS 支持
<a name="apigateway-cors-request-types"></a>

*跨源* HTTP 请求将向以下项发出：
+ 一个不同的*域*（例如，从 `example.com` 到 `amazondomains.com`）
+ 一个不同的*子域*（例如，从 `example.com` 到 `petstore.example.com`）
+ 一个不同的*端口*（例如，从 `example.com` 到 `example.com:10777`）
+ 一个不同的*协议*（例如，从 `https://example.com` 到 `http://example.com`）

 如果您无法访问自己的 API 并收到包含 `Cross-Origin Request Blocked` 的错误消息，则可能需要启用 CORS。

跨源 HTTP 请求可分为两种类型：*简单* 请求和*非简单* 请求。

## 为简单请求启用 CORS
<a name="apigateway-cors-simple-request"></a>

如果满足以下所有条件，则 HTTP 请求为*简单* 请求：
+ 其针对仅允许 `GET`、`HEAD` 和 `POST` 请求的 API 资源发出。
+ 如果它是一个 `POST` 方法请求，则它必须包含 `Origin` 标头。
+ 请求负载内容类型为 `text/plain`、`multipart/form-data` 或 `application/x-www-form-urlencoded`。
+ 请求不包含自定义标头。
+ [简单请求的 Mozilla CORS 文档](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests)中列出的任何其他要求。

对于简单的跨源 `POST` 方法请求，来自资源的响应需要包含标头 `Access-Control-Allow-Origin: '*'` 或 `Access-Control-Allow-Origin:'origin'`。

所有其他跨源 HTTP 请求均为*非简单* 请求。

## 为非简单请求启用 CORS
<a name="apigateway-enable-cors-non-simple"></a>

如果 API 的资源收到非简单请求，则必须根据集成类型启用额外的 CORS 支持。

### 为非代理集成启用 CORS
<a name="apigateway-enable-cors-mock"></a>

对于这些集成，[CORS 协议](https://fetch.spec.whatwg.org/#http-cors-protocol)要求浏览器在发送实际请求之前向服务器发送一个预检请求，并等待来自服务器的批准（或对于凭证的请求）。您必须配置您的 API 以向预检请求发送适当的响应。

 要创建预检响应，请执行以下操作：

1. 使用模拟集成创建 `OPTIONS` 方法。

1. 将以下响应标头添加到 200 方法响应中：
   + `Access-Control-Allow-Headers`
   + `Access-Control-Allow-Methods`
   + `Access-Control-Allow-Origin`

1. 将集成传递行为设置为 `NEVER`。在这种情况下，将拒绝未映射内容类型的方法请求，并返回“HTTP 415 不支持的媒体类型”响应。有关更多信息，请参阅[API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

1. 输入响应标头的值。要允许所有来源、所有方法和通用标头，请使用以下标头值：
   + `Access-Control-Allow-Headers: 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'`
   + `Access-Control-Allow-Methods: 'DELETE,GET,HEAD,OPTIONS,PUT,POST,PATCH'`
   + `Access-Control-Allow-Origin: '*'`

创建预检请求后，对于至少所有 200 响应，必须为所有启用 CORS 的方法返回 `Access-Control-Allow-Origin: '*'` 或 `Access-Control-Allow-Origin:'origin'` 标头。

### 使用 AWS 管理控制台为非代理集成启用 CORS
<a name="apigateway-enable-cors-mock-console"></a>

您可以使用 AWS 管理控制台来启用 CORS。API Gateway 会创建 `OPTIONS` 方法，并尝试将 `Access-Control-Allow-Origin` 标头添加到现有的方法集成响应中。这并不总是有效，有时您需要手动修改集成响应，以便为至少所有 200 响应的所有启用 CORS 的方法返回 `Access-Control-Allow-Origin` 标头。

如果 API 的二进制媒体类型设置为 `*/*`，则当 API Gateway 创建 `OPTIONS` 方法时，请将 `contentHandling` 更改为 `CONVERT_TO_TEXT`。

以下 [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration.html) 命令将集成请求的 `contentHandling` 更改为 `CONVERT_TO_TEXT`：

```
aws apigateway update-integration \
  --rest-api-id abc123 \
  --resource-id aaa111 \
  --http-method OPTIONS \
  --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
```

以下 [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) 命令将集成响应的 `contentHandling` 更改为 `CONVERT_TO_TEXT`：

```
aws apigateway update-integration-response \
  --rest-api-id abc123 \
  --resource-id aaa111 \
  --http-method OPTIONS \
  --status-code 200 \
  --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
```

## 为代理集成启用 CORS 支持
<a name="apigateway-enable-cors-proxy"></a>

对于 Lambda 代理集成或 HTTP 代理集成，您的后端负责返回 `Access-Control-Allow-Origin`、`Access-Control-Allow-Methods` 和 `Access-Control-Allow-Headers` 标头，因为代理集成不返回集成响应。

以下 Lambda 函数示例返回所需的 CORS 标头：

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

```
export const handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "https://www.example.com",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
        },
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
```

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

```
import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Origin': 'https://www.example.com',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        },
        'body': json.dumps('Hello from Lambda!')
    }
```

------

**Topics**
+ [确定是否启用 CORS 支持](#apigateway-cors-request-types)
+ [为简单请求启用 CORS](#apigateway-cors-simple-request)
+ [为非简单请求启用 CORS](#apigateway-enable-cors-non-simple)
+ [为代理集成启用 CORS 支持](#apigateway-enable-cors-proxy)
+ [使用 API Gateway 控制台对资源启用 CORS](how-to-cors-console.md)
+ [使用 API Gateway 导入 API 在资源上启用 CORS](enable-cors-for-resource-using-swagger-importer-tool.md)
+ [在 CORS 中测试 API Gateway API](apigateway-test-cors.md)

# 使用 API Gateway 控制台对资源启用 CORS
<a name="how-to-cors-console"></a>

您可以使用 API Gateway 控制台为已创建的 REST API 资源上的一个或所有方法启用 CORS 支持。启用 COR 支持后，将集成传递行为设置为 `NEVER`。在这种情况下，将拒绝未映射内容类型的方法请求，并返回“HTTP 415 不支持的媒体类型”响应。有关更多信息，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

**重要**  
资源可以包含子资源。为某个资源及其方法启用 CORS 支持不会以递归方式为子资源及其方法启用它。

**在 REST API 资源上启用 CORS 支持**

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

1. 选择一个 API。

1. 在**资源**下选择一个资源。

1. 在**资源详细信息**部分，选择**启用 CORS**。

      
![\[在“资源”窗格中，选择“启用 CORS”。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/amazon-api-gateway-new-console-enable-cors.png)

1.  在**启用 CORS** 框中，执行以下操作：

   1. （可选）如果您创建了自定义网关响应并希望为响应启用 CORS 支持，请选择一种网关响应。

   1. 选择各方法以启用 CORS 支持。`OPTION` 方法必须启用 CORS。

      如果您为某个 `ANY` 方法启用 CORS 支持，则会为所有方法启用 CORS。

   1.  在 **Access-Control-Allow-Headers** 输入字段中，输入静态字符串，该字符串是客户端必须在实际资源请求中提交的标头列表，以逗号分隔。使用控制台提供的 `'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'` 标头列表，或指定您自己的标头。

   1. 将控制台提供的值 `'*'` 用作 **Access-Control-Allow-Origin** 标头值，以支持来自所有源的访问请求，或指定可以访问该资源的源。

   1. 选择**保存**。  
![\[选择允许的标头\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/amazon-api-gateway-new-console-enable-cors-resources.png)
**重要**  
 如果在代理集成中将以上说明应用于 `ANY` 方法，那么将不会设置任何适用的 CORS 标头。相反，您的后端必须返回适用的 CORS 标头，例如 `Access-Control-Allow-Origin`。

在 `GET` 方法上启用 CORS 后，如果资源中没有 `OPTIONS` 方法，则该方法将添加到资源中。`OPTIONS` 方法的 `200` 响应会自动配置为返回三个 `Access-Control-Allow-*` 标头，以完成预检握手。此外，默认情况下，实际 (`GET`) 方法还会配置为在 200 响应内返回 `Access-Control-Allow-Origin` 标头。对于其他类型的响应，如果您不希望返回 `Cross-origin access` 错误，您将需要手动对其进行配置，以返回带有“\$1”或特定源的 `Access-Control-Allow-Origin'` 标头。

在您的资源上启用 CORS 支持后，您必须部署或重新部署 API 以使新设置生效。有关更多信息，请参阅 [创建 部署。](set-up-deployments.md#create-deployment)。

**注意**  
如果按照此过程操作后无法在资源上启用 CORS 支持，我们建议您将您的 CORS 配置与示例 API `/pets` 资源进行比较。要了解如何创建示例 API，请参阅[教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

# 使用 API Gateway 导入 API 在资源上启用 CORS
<a name="enable-cors-for-resource-using-swagger-importer-tool"></a>

如果您使用 [API Gateway 导入 API](api-gateway-import-api.md)，则可以使用 OpenAPI 文件设置 CORS 支持。您必须先在您的资源中定义可返回所需标头的 `OPTIONS` 方法。

**注意**  
Web 浏览器预计接受 CORS 请求的每个 API 方法中会设置 Access-Control-Allow 标头和 Access-Control-Allow-Origin 标头。此外，某些浏览器首先向同一资源中的 `OPTIONS` 方法发出 HTTP 请求，然后预计收到相同的标头。

## `Options` 方法示例
<a name="enable-cors-for-resource-using-swagger-importer-tool-options"></a>

以下示例创建了一个 `OPTIONS` 方法以进行模拟集成。

------
#### [ OpenAPI 3.0 ]

```
/users:
  options:
    summary: CORS support
    description: |
      Enable CORS by returning correct headers
    tags:
    - CORS
    responses:
      200:
        description: Default response for CORS method
        headers:
          Access-Control-Allow-Origin:
            schema:
              type: "string"
          Access-Control-Allow-Methods:
            schema:
              type: "string"
          Access-Control-Allow-Headers:
            schema:
              type: "string"
        content: {}
    x-amazon-apigateway-integration:
      type: mock
      requestTemplates:
        application/json: "{\"statusCode\": 200}"
      passthroughBehavior: "never"
      responses:
        default:
          statusCode: "200"
          responseParameters:
            method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
            method.response.header.Access-Control-Allow-Methods: "'*'"
            method.response.header.Access-Control-Allow-Origin: "'*'"
```

------
#### [ OpenAPI 2.0 ]

```
/users: 
   options:
      summary: CORS support
      description: |
        Enable CORS by returning correct headers
      consumes:
        - "application/json"
      produces:
        - "application/json"
      tags:
        - CORS
      x-amazon-apigateway-integration:
        type: mock
        requestTemplates: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        responses:
          "default":
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Methods : "'*'"
              method.response.header.Access-Control-Allow-Origin : "'*'"
      responses:
        200:
          description: Default response for CORS method
          headers:
            Access-Control-Allow-Headers:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Origin:
              type: "string"
```

------

在您为资源配置 `OPTIONS` 方法后，可以将所需的标头添加到同一资源中需要接受 CORS 请求的其他方法。

1. 将 **Access-Control-Allow-Origin** 和**标头**声明为响应类型。

------
#### [ OpenAPI 3.0 ]

   ```
       responses:
         200:
           description: Default response for CORS method
           headers:
             Access-Control-Allow-Origin:
               schema:
                 type: "string"
             Access-Control-Allow-Methods:
               schema:
                 type: "string"
             Access-Control-Allow-Headers:
               schema:
                 type: "string"
           content: {}
   ```

------
#### [ OpenAPI 2.0 ]

   ```
       responses:
           200:
             description: Default response for CORS method
             headers:
               Access-Control-Allow-Headers:
                 type: "string"
               Access-Control-Allow-Methods:
                 type: "string"
               Access-Control-Allow-Origin:
                 type: "string"
   ```

------

1. 在 `x-amazon-apigateway-integration` 标签中，为这些标头设置到静态值的映射：

------
#### [ OpenAPI 3.0 ]

   ```
       responses:
           default:
             statusCode: "200"
             responseParameters:
               method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
               method.response.header.Access-Control-Allow-Methods: "'*'"
               method.response.header.Access-Control-Allow-Origin: "'*'"
             responseTemplates:
               application/json: |
                 {}
   ```

------
#### [ OpenAPI 2.0 ]

   ```
       responses:
             "default":
               statusCode: "200"
               responseParameters:
                 method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                 method.response.header.Access-Control-Allow-Methods : "'*'"
                 method.response.header.Access-Control-Allow-Origin : "'*'"
   ```

------

## API 示例
<a name="enable-cors-for-resource-using-swagger-importer-tool-complete-example"></a>

以下示例创建一个完整的 API，其中包含一个 `OPTIONS` 方法和一个集成了 `HTTP` 的 `GET` 方法。

------
#### [ OpenAPI 3.0 ]

```
openapi: "3.0.1"
info:
  title: "cors-api"
  description: "cors-api"
  version: "2024-01-16T18:36:01Z"
servers:
- url: "/{basePath}"
  variables:
    basePath:
      default: "/test"
paths:
  /:
    get:
      operationId: "GetPet"
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: "string"
          content: {}
      x-amazon-apigateway-integration:
        httpMethod: "GET"
        uri: "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets"
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "never"
        type: "http"
    options:
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: "string"
            Access-Control-Allow-Methods:
              schema:
                type: "string"
            Access-Control-Allow-Headers:
              schema:
                type: "string"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Empty"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        type: "mock"
components:
  schemas:
    Empty:
      type: "object"
```

------
#### [  OpenAPI 2.0  ]

```
swagger: "2.0"
info:
  description: "cors-api"
  version: "2024-01-16T18:36:01Z"
  title: "cors-api"
basePath: "/test"
schemes:
- "https"
paths:
  /:
    get:
      operationId: "GetPet"
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
      x-amazon-apigateway-integration:
        httpMethod: "GET"
        uri: "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets"
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "never"
        type: "http"
    options:
      consumes:
      - "application/json"
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        type: "mock"
definitions:
  Empty:
    type: "object"
```

------

# 在 CORS 中测试 API Gateway API
<a name="apigateway-test-cors"></a>

您可以通过调用 API 并检查响应中的 CORS 标头来测试 API 的 CORS 配置。以下 `curl` 命令将 OPTIONS 请求发送到已部署的 API。

```
curl -v -X OPTIONS https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}
```

```
< HTTP/1.1 200 OK
< Date: Tue, 19 May 2020 00:55:22 GMT
< Content-Type: application/json
< Content-Length: 0
< Connection: keep-alive
< x-amzn-RequestId: a1b2c3d4-5678-90ab-cdef-abc123
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token
< x-amz-apigw-id: Abcd=
< Access-Control-Allow-Methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
```

响应中的 `Access-Control-Allow-Origin`、`Access-Control-Allow-Headers` 和 `Access-Control-Allow-Methods` 标头显示此 API 支持 CORS。有关更多信息，请参阅 [针对 API Gateway 中的 REST API 的 CORS](how-to-cors.md)。

# 针对 API Gateway 中的 REST API 的二进制媒体类型
<a name="api-gateway-payload-encodings"></a>

在 API Gateway 中，API 请求和响应具有文本或二进制负载。文本负载是 `UTF-8` 编码的 JSON 字符串。二进制负载是文本负载以外的负载。例如，二进制负载可以是 JPEG 文件、GZip 文件或 XML 文件。支持二进制媒体所需的 API 配置取决于 API 是使用代理集成还是非代理集成。

如果您使用带有效载荷响应流式传输的代理集成，则无需配置二进制媒体类型。有关更多信息，请参阅 [在 API Gateway 中流式传输代理集成的集成响应](response-transfer-mode.md)。

## AWS Lambda 代理集成
<a name="api-gateway-payload-encodings-proxy"></a>

要处理 AWS Lambda 代理集成的二进制负载，您必须对函数的响应进行 base64 编码。还必须为 API 配置 [binaryMediaTypes](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apigw-Type-RestApi-binaryMediaTypes)。API 的 `binaryMediaTypes` 配置是 API 视为二进制数据的内容类型的列表。示例二进制媒体类型包括 `image/png` 或 `application/octet-stream`。您可以使用通配符 (`*`) 来涵盖多种媒体类型。

API Gateway 使用来自客户端的第一个 `Accept` 标头来确定响应是否应返回二进制媒体。要在无法控制 `Accept` 标头值（如浏览器中的请求）的顺序时返回二进制媒体，请将 API 的二进制媒体类型设置为 `*/*`。

有关代码示例，请参阅 [从 API Gateway 中的 Lambda 代理集成返回二进制媒体](lambda-proxy-binary-media.md)。

如果您使用带有效载荷响应流式传输的 Lambda 代理集成，则无需配置二进制媒体类型。有关更多信息，请参阅 [在 API Gateway 中设置采用有效载荷响应流式传输的 Lambda 代理集成](response-transfer-mode-lambda.md)。

## 非代理集成
<a name="api-gateway-payload-encodings-non-proxy"></a>

要处理非代理集成的二进制负载，请将媒体类型添加到 `RestApi` 资源的 [binaryMediaTypes](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apigw-Type-RestApi-binaryMediaTypes) 列表中。API 的 `binaryMediaTypes` 配置是 API 视为二进制数据的内容类型的列表。或者，您可以设置 [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 和 [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源上的 [contentHandling](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#contentHandling) 属性。`contentHandling` 值可以是 `CONVERT_TO_BINARY`、`CONVERT_TO_TEXT` 或未定义。

**注意**  
对于 `MOCK` 或私有集成，AWS 管理控制台中不支持设置 `contentHandling` 属性。您必须使用 AWS CLI、CloudFormation 或 SDK 来设置 `contentHandling` 属性。

根据 `contentHandling` 值，以及响应的 `Content-Type` 标头或传入请求的 `Accept` 标头是否匹配 `binaryMediaTypes` 列表中的某个条目，API Gateway 可以将原始二进制字节编码为 Base64 编码的字符串，将 Base64 编码的字符串解码回其原始字节，或者直接传递正文而不作修改。

您必须按如下方式配置 API，以对 API Gateway 中 API 的二进制负载提供支持：
+ 将所需的二进制媒体类型添加到 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源的 `binaryMediaTypes` 列表中。如果未定义此属性和 `contentHandling` 属性，会将负载作为 UTF-8 编码的 JSON 字符串进行处理。
+ 解决 [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 资源的 `contentHandling` 属性。
  + 要将请求负载从 base64 编码的字符串转换为其二进制 blob，请将此属性设置为 `CONVERT_TO_BINARY`。
  + 要将请求负载从二进制 blob 转换为 base64 编码的字符串，请将此属性设置为 `CONVERT_TO_TEXT`。
  + 要在不修改的情况下传递负载，请将此属性保留为未定义。要在不修改的情况下传递二进制负载，还必须确保 `Content-Type` 与其中一个 `binaryMediaTypes` 条目匹配，并且已为 API 启用[传递行为](integration-passthrough-behaviors.md)。
+ 设置 [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源的 `contentHandling` 属性。`contentHandling` 属性、客户端请求中的 `Accept` 标头以及 API 的 `binaryMediaTypes` 组合决定了 API Gateway 如何处理内容类型转换。有关详细信息，请参阅[API Gateway 中的内容类型转换](api-gateway-payload-encodings-workflow.md)。

**重要**  
如果某个请求在其 `Accept` 标头中包含多个媒体类型，API Gateway 将只接受第一个 `Accept` 媒体类型。如果无法控制 `Accept` 媒体类型的顺序并且二进制内容的媒体类型不是列表中的第一个，则添加 API 的 `Accept` 列表中的第一个 `binaryMediaTypes` 媒体类型。API Gateway 将以二进制形式处理此列表中的所有内容类型。  
例如，要在浏览器中使用 `<img>` 元素发送 JPEG 文件，该浏览器可能会在请求中发送 `Accept:image/webp,image/*,*/*;q=0.8`。将 `image/webp` 添加到 `binaryMediaTypes` 列表后，终端节点将收到二进制形式的 JPEG 文件。

有关 API Gateway 如何处理文本和二进制负载的详细信息，请参阅 [API Gateway 中的内容类型转换](api-gateway-payload-encodings-workflow.md)。

# API Gateway 中的内容类型转换
<a name="api-gateway-payload-encodings-workflow"></a>

 API 的 `binaryMediaTypes`、客户端请求中的标头和集成 `contentHandling` 属性的组合决定了 API Gateway 对负载编码的方式。

下表显示了 API Gateway 如何转换某个请求的 `Content-Type` 标头的特定配置的请求有效载荷、[RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源的 `binaryMediaTypes` 列表以及 [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) 资源的 `contentHandling` 属性值。


| 方法请求负载 | 请求 `Content-Type` 标头 | `binaryMediaTypes` | `contentHandling` | 集成请求负载 | 
| --- | --- | --- | --- | --- | 
| 文本数据 | 任意数据类型 | 未定义 | 未定义 | UTF8 编码的字符串 | 
| 文本数据 | 任意数据类型 | 未定义 | CONVERT\$1TO\$1BINARY | Base64 解码的二进制 blob | 
| 文本数据 | 任意数据类型 | 未定义 | CONVERT\$1TO\$1TEXT | UTF8 编码的字符串 | 
| 文本数据 | 文本数据类型 | 包含匹配的媒体类型的集合 | 未定义 | 文本数据 | 
| 文本数据 | 文本数据类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1BINARY | Base64 解码的二进制 blob | 
| 文本数据 | 文本数据类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1TEXT | 文本数据 | 
| 二进制数据 | 二进制数据类型 | 包含匹配的媒体类型的集合 | 未定义 | 二进制数据 | 
| 二进制数据 | 二进制数据类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1BINARY | 二进制数据 | 
| 二进制数据 | 二进制数据类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1TEXT | Base64 编码的字符串 | 

下表显示了 API Gateway 如何转换某个请求的 `Accept` 标头的特定配置的响应有效载荷、[RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源的 `binaryMediaTypes` 列表以及 [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 资源的 `contentHandling` 属性值。

**重要**  
 如果某个请求在其 `Accept` 标头中包含多个媒体类型，API Gateway 将只接受第一个 `Accept` 媒体类型。如果无法控制 `Accept` 媒体类型的顺序并且二进制内容的媒体类型不是列表中的第一个，则添加 API 的 `Accept` 列表中的第一个 `binaryMediaTypes` 媒体类型。API Gateway 将以二进制形式处理此列表中的所有内容类型。  
例如，要在浏览器中使用 `<img>` 元素发送 JPEG 文件，该浏览器可能会在请求中发送 `Accept:image/webp,image/*,*/*;q=0.8`。将 `image/webp` 添加到 `binaryMediaTypes` 列表后，端点将收到二进制形式的 JPEG 文件。


| 集成响应负载 | 请求 `Accept` 标头 | `binaryMediaTypes` | `contentHandling` | 方法响应负载 | 
| --- | --- | --- | --- | --- | 
| 文本或二进制数据 | 文本类型 | 未定义 | 未定义 | UTF8 编码的字符串 | 
| 文本或二进制数据 | 文本类型 | 未定义 | CONVERT\$1TO\$1BINARY | Base64 解码的 blob | 
| 文本或二进制数据 | 文本类型 | 未定义 | CONVERT\$1TO\$1TEXT | UTF8 编码的字符串 | 
| 文本数据 | 文本类型 | 包含匹配的媒体类型的集合 | 未定义 | 文本数据 | 
| 文本数据 | 文本类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1BINARY | Base64 解码的 blob | 
| 文本数据 | 文本类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1TEXT | UTF8 编码的字符串 | 
| 文本数据 | 二进制类型 | 包含匹配的媒体类型的集合 | 未定义 | Base64 解码的 blob | 
| 文本数据 | 二进制类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1BINARY | Base64 解码的 blob | 
| 文本数据 | 二进制类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1TEXT | UTF8 编码的字符串 | 
| 二进制数据 | 文本类型 | 包含匹配的媒体类型的集合 | 未定义 | Base64 编码的字符串 | 
| 二进制数据 | 文本类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1BINARY | 二进制数据 | 
| 二进制数据 | 文本类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1TEXT | Base64 编码的字符串 | 
| 二进制数据 | 二进制类型 | 包含匹配的媒体类型的集合 | 未定义 | 二进制数据 | 
| 二进制数据 | 二进制类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1BINARY | 二进制数据 | 
| 二进制数据 | 二进制类型 | 包含匹配的媒体类型的集合 | CONVERT\$1TO\$1TEXT | Base64 编码的字符串 | 

将文本负载转换为二进制 blob 时，API Gateway 假定文本数据是 Base64 编码的字符串，并将二进制数据作为 Base64 解码的 blob 输出。如果转换失败，它将返回一个 `500` 响应，指示出现 API 配置错误。尽管必须对 API 启用[传递行为](integration-passthrough-behaviors.md)，但您不用提供此类转换的映射模板。

将二进制负载转换为文本字符串时，API Gateway 始终对二进制数据应用 Base64 编码。您可以定义此类负载的映射模板，但只能通过 `$input.body` 访问映射模板中的 Base64 编码字符串，如映射模板示例的以下摘录中所示。

```
{   
    "data": "$input.body"
}
```

要直接传递二进制负载而不作修改，必须对 API 启用[传递行为](integration-passthrough-behaviors.md)。

# 使用 API Gateway 控制台启用二进制支持
<a name="api-gateway-payload-encodings-configure-with-console"></a>

本节说明如何使用 API Gateway 控制台启用二进制支持。例如，我们使用一个与 Amazon S3 集成的 API。我们的任务重点是设置受支持的媒体类型并指定如何处理负载。有关如何创建与 Amazon S3 集成的 API 的详细信息，请参阅[教程：创建 REST API 作为 Amazon S3 代理](integrating-api-with-aws-services-s3.md)。

**使用 API Gateway 控制台启用二进制支持**

1. 设置 API 的二进制媒体类型：

   1. 创建新 API 或选择现有 API。在本例中，我们将 API 命名为 `FileMan`。

   1. 在主导航面板中所选的 API 之下，选择 **API 设置**。

   1. 在 **API 设置**窗格中的**二进制媒体类型**部分，选择**管理媒体类型**。

   1. 选择**添加二进制媒体类型**。

   1. 在文本输入字段中输入所需的媒体类型，例如 **image/png**。如果需要，请重复此步骤，添加更多媒体类型。要支持所有二进制媒体类型，请指定 `*/*`。

   1. 选择**保存更改**。

1. 设置如何针对 API 方法处理消息负载：

   1. 创建新资源或选择 API 中的现有资源。在本例中，我们使用 `/{folder}/{item}` 资源。

   1. 对该资源创建新方法或选择一个现有方法。例如，我们使用与 Amazon S3 中的 `GET /{folder}/{item}` 操作集成的 `Object GET` 方法。

   1. 对于**内容处理**，选择一个选项。

         
![\[在 API Gateway 控制台中设置 GET 方法。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/binary-support-content-handling-on-method-new-console.png)

      如果不想在客户端和后端接受相同的二进制格式时转换正文，则选择**传递**。当存在后端要求将二进制请求负载作为 JSON 属性传入等情况时，选择**转换为文本**以将二进制正文转换为 Base64 编码的字符串。当客户端提交 Base64 编码的字符串且后端需要原始二进制格式，或者当端点返回 Base64 编码的字符串且客户端只接受二进制输出时，选择**转换为二进制**。

   1. 对于**请求正文传递**，选择**当未定义模板时（推荐）**，以在请求正文上启用传递行为。

      您也可以选择**从不**。这意味着 API 将拒绝其内容类型没有映射模板的数据。

   1. 在集成请求中保留传入请求的 `Accept` 标头。如果您已将 `contentHandling` 设置为 `passthrough` 并且希望在运行时覆盖该设置，则应执行此操作。

         
![\[在集成请求中保留 Accept 标头。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/binary-support-preserve-incoming-accept-header-new-console.png)

   1. 转换为文本时，请定义映射模板，以将 Base64 编码的二进制数据转换为所需格式。

      以下是用于转换为文本的映射模板的示例：

      ```
      {
        "operation": "thumbnail",
        "base64Image": "$input.body"
      }
      ```

      此映射模板的格式取决于输入的端点要求。

   1. 选择**保存**。

# 使用 API Gateway REST API 启用二进制支持
<a name="api-gateway-payload-encodings-configure-with-control-service-api"></a>

以下任务演示如何使用 API Gateway REST API 调用来启用二进制支持。

**Topics**
+ [向 API 添加和更新受支持的二进制媒体类型](#api-gateway-payload-encodings-setup-with-api-set-encodings-map)
+ [配置请求负载转换](#api-gateway-payload-encodings-setup-with-api-set-integration-request-encoding)
+ [配置响应负载转换](#api-gateway-payload-encodings-setup-with-api-set-integration-response-encoding)
+ [将二进制数据转换为文本数据](#api-gateway-payload-encodings-convert-binary-to-string)
+ [将文本数据转换为二进制负载](#api-gateway-payload-encodings-convert-string-to-binary)
+ [传递二进制负载](#api-gateway-payload-encodings-pass-binary-as-is)

## 向 API 添加和更新受支持的二进制媒体类型
<a name="api-gateway-payload-encodings-setup-with-api-set-encodings-map"></a>

要允许 API Gateway 支持新的二进制媒体类型，必须将该二进制媒体类型添加到 `binaryMediaTypes` 资源的 `RestApi` 列表中。例如，要让 API Gateway 处理 JPEG 图像，应向 `PATCH` 资源提交 `RestApi` 请求：

```
PATCH /restapis/<restapi_id>

{
  "patchOperations" : [ {
    "op" : "add",
    "path" : "/binaryMediaTypes/image~1jpeg"
  } 
 ]
}
```

属于 `image/jpeg` 属性值一部分的 MIME 类型规范 `path` 将转义为 `image~1jpeg`。

要更新受支持的二进制媒体类型，请替换或删除 `binaryMediaTypes` 资源的 `RestApi` 列表中的该媒体类型。例如，要将二进制支持从 JPEG 文件更改为原始字节，请向 `PATCH` 资源提交 `RestApi` 请求，如下所示：

```
PATCH /restapis/<restapi_id>

{
  "patchOperations" : [{
    "op" : "replace",
    "path" : "/binaryMediaTypes/image~1jpeg",
    "value" : "application/octet-stream"
  },
  {
    "op" : "remove",
    "path" : "/binaryMediaTypes/image~1jpeg"
  }]
}
```

## 配置请求负载转换
<a name="api-gateway-payload-encodings-setup-with-api-set-integration-request-encoding"></a>

如果端点需要二进制输入，则将 `contentHandling` 资源的 `Integration` 属性设置为 `CONVERT_TO_BINARY`。为此，请提交 `PATCH` 请求，如下所示：

```
PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration

{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "/contentHandling",
    "value" : "CONVERT_TO_BINARY"
  }]
}
```

## 配置响应负载转换
<a name="api-gateway-payload-encodings-setup-with-api-set-integration-response-encoding"></a>

如果客户端接受二进制 blob 形式的结果而不是从端点返回的 Base64 编码的负载，则将 `IntegrationResponse` 资源的 `contentHandling` 属性设置为 `CONVERT_TO_BINARY`。为此，请提交 `PATCH` 请求，如下所示：

```
PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration/responses/<status_code>

{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "/contentHandling",
    "value" : "CONVERT_TO_BINARY"
  }]
}
```

## 将二进制数据转换为文本数据
<a name="api-gateway-payload-encodings-convert-binary-to-string"></a>

要通过 API Gateway 将二进制数据作为输入的 JSON 属性发送到 AWS Lambda 或 Kinesis，请执行以下操作：

1. 通过将新的二进制媒体类型 `application/octet-stream` 添加到 API 的 `binaryMediaTypes` 列表，启用 API 的二进制负载支持。

   ```
   PATCH /restapis/<restapi_id>
   
   {
     "patchOperations" : [ {
       "op" : "add",
       "path" : "/binaryMediaTypes/application~1octet-stream"
     } 
    ]
   }
   ```

1. 在 `CONVERT_TO_TEXT` 资源的 `contentHandling` 属性上设置 `Integration`，并提供映射模板以将二进制数据的 Base64 编码字符串分配给 JSON 属性。在以下示例中，JSON 属性为 `body`，并且 `$input.body` 保存 Base64 编码的字符串。

   ```
   PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration
   
   {
     "patchOperations" : [
       {
         "op" : "replace",
         "path" : "/contentHandling",
         "value" : "CONVERT_TO_TEXT"
       },
       {
         "op" : "add",
         "path" : "/requestTemplates/application~1octet-stream",
         "value" : "{\"body\": \"$input.body\"}"
       }
     ]
   }
   ```

## 将文本数据转换为二进制负载
<a name="api-gateway-payload-encodings-convert-string-to-binary"></a>

假设 Lambda 函数返回一个 Base64 编码字符串形式的图像文件。要通过 API Gateway 将此二进制输出传递到客户端，请执行以下操作：

1. 通过添加二进制媒体类型 `binaryMediaTypes` (如果该类型尚不在列表中) 来更新 API 的 `application/octet-stream` 列表。

   ```
   PATCH /restapis/<restapi_id>
   
   {
     "patchOperations" : [ {
       "op" : "add",
       "path" : "/binaryMediaTypes/application~1octet-stream",
     }]
   }
   ```

1.  将 `contentHandling` 资源的 `Integration` 属性设置为 `CONVERT_TO_BINARY`。请勿定义映射模板。如果不定义映射模板，API Gateway 会调用传递模板，以将 Base64 解码的二进制 blob 作为图像文件返回给客户端。

   ```
   PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration/responses/<status_code>
   
   {
     "patchOperations" : [
       {
         "op" : "replace",
         "path" : "/contentHandling",
         "value" : "CONVERT_TO_BINARY"
       }
     ]
   }
   ```

## 传递二进制负载
<a name="api-gateway-payload-encodings-pass-binary-as-is"></a>

 要使用 API Gateway 将图像存储在 Amazon S3 存储桶中，请执行以下操作：

1. 通过添加二进制媒体类型 `binaryMediaTypes`（如果该类型尚不在列表中）来更新 API 的 `application/octet-stream` 列表。

   ```
   PATCH /restapis/<restapi_id>
   
   {
     "patchOperations" : [ {
       "op" : "add",
       "path" : "/binaryMediaTypes/application~1octet-stream"
     }
    ]
   }
   ```

1. 在 `contentHandling` 资源的 `Integration` 属性上，设置 `CONVERT_TO_BINARY`。将 `WHEN_NO_MATCH` 设置为 `passthroughBehavior` 属性值，而不定义映射模板。这使 API Gateway 能够调用传递模板。

   ```
   PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration
   
   {
     "patchOperations" : [
       {
         "op" : "replace",
         "path" : "/contentHandling",
         "value" : "CONVERT_TO_BINARY"
       },
       {
         "op" : "replace",
         "path" : "/passthroughBehaviors",
         "value" : "WHEN_NO_MATCH"
       }
     ]
   }
   ```

# 导入和导出 API Gateway 的内容编码
<a name="api-gateway-payload-encodings-import-and-export"></a>

 要导入 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 上的 `binaryMediaTypes` 列表，请使用 API 的 OpenAPI 定义文件的以下 API Gateway 扩展。该扩展也用于导出 API 设置。
+ [x-amazon-apigateway-binary-media-types 属性](api-gateway-swagger-extensions-binary-media-types.md)

要导入和导出 `contentHandling` 或 `Integration` 资源的 `IntegrationResponse` 属性值，请使用 OpenAPI 定义的以下 API Gateway 扩展：
+ [x-amazon-apigateway-integration 对象](api-gateway-swagger-extensions-integration.md)
+ [x-amazon-apigateway-integration.response 对象](api-gateway-swagger-extensions-integration-response.md)

# 从 API Gateway 中的 Lambda 代理集成返回二进制媒体
<a name="lambda-proxy-binary-media"></a>

要从 [AWS Lambda 代理集成](set-up-lambda-proxy-integrations.md)返回二进制媒体，请对来自 Lambda 函数的响应进行 base64 编码。还必须[配置 API 的二进制媒体类型](api-gateway-payload-encodings-configure-with-console.md)。当您配置 API 的二进制媒体类型时，您的 API 会将该内容类型视为二进制数据。负载大小限制为 10 MB。

**注意**  
要使用 Web 浏览器调用具有此示例集成的 API，请将 API 的二进制媒体类型设置为 `*/*`。API Gateway 使用来自客户端的第一个 `Accept` 标头来确定响应是否应返回二进制媒体。要在无法控制 `Accept` 标头值（如浏览器中的请求）的顺序时返回二进制媒体，请将 API 的二进制媒体类型设置为 `*/*`（对于所有内容类型）。

以下 Lambda 函数示例可以从 Amazon S3 返回二进制图像或将文本返回到客户端。该函数的响应包括一个 `Content-Type` 标头，用于向客户端指示它返回的数据类型。函数有条件地设置其响应中的 `isBase64Encoded` 属性，具体取决于它返回的数据类型。

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

```
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3"

const client = new S3Client({region: 'us-east-2'});

export const handler = async (event) => {

  var randomint = function(max) {
    return Math.floor(Math.random() * max);
  }
  var number = randomint(2);
  if (number == 1){ 
    const input = {
      "Bucket" : "bucket-name",
      "Key" : "image.png"
      }
    try {
      const command = new GetObjectCommand(input)
      const response = await client.send(command);
      var str = await response.Body.transformToByteArray();
    } catch (err) {
      console.error(err);
    }
    const base64body = Buffer.from(str).toString('base64');
    return {
      'headers': { "Content-Type": "image/png" },
      'statusCode': 200,
      'body': base64body,
      'isBase64Encoded': true
      }
    } else {
        return {
        'headers': { "Content-Type": "text/html" },
        'statusCode': 200,
        'body': "<h1>This is text</h1>",
        }
    }
}
```

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

```
import base64
import boto3
import json
import random

s3 = boto3.client('s3')

def lambda_handler(event, context):
    number = random.randint(0,1)
    if number == 1:
        response = s3.get_object(
            Bucket='bucket-name',
            Key='image.png',
        )
        image = response['Body'].read()
        return {
            'headers': { "Content-Type": "image/png" },
            'statusCode': 200,
            'body': base64.b64encode(image).decode('utf-8'),
            'isBase64Encoded': True
        }
    else:
        return {
            'headers': { "Content-type": "text/html" },
            'statusCode': 200,
            'body': "<h1>This is text</h1>",
        }
```

------

要了解有关二进制媒体类型的更多信息，请参阅 [针对 API Gateway 中的 REST API 的二进制媒体类型](api-gateway-payload-encodings.md)。

# 通过 API Gateway API 访问 Amazon S3 中的二进制文件
<a name="api-gateway-content-encodings-examples-image-s3"></a>

以下示例显示了用于访问 Amazon S3 中图像的 OpenAPI 文件如何从 Amazon S3 下载图像以及如何将图像上传到 Amazon S3。

**Topics**
+ [用于访问 Amazon S3 中图像的示例 API 的 OpenAPI 文件](#api-gateway-content-encodings-example-image-s3-swagger-file)
+ [从 Amazon S3 下载图像](#api-gateway-content-encodings-example-download-image-from-s3)
+ [将图像上传到 Amazon S3](#api-gateway-content-encodings-example-upload-image-to-s3)

## 用于访问 Amazon S3 中图像的示例 API 的 OpenAPI 文件
<a name="api-gateway-content-encodings-example-image-s3-swagger-file"></a>

以下 OpenAPI 文件显示了一个示例 API，阐明了如何从 Amazon S3 下载图像文件以及如何将图像文件上传到 Amazon S3。此 API 公开了下载和上传指定图像文件所用的 `GET /s3?key={file-name}` 和 `PUT /s3?key={file-name}` 方法。`GET` 方法按照所提供的映射模板，在一个 200 OK 响应中返回 Base64 编码字符串形式的图像文件作为 JSON 输出的一部分。`PUT` 方法将原始二进制 blob 作为输入，并返回一个负载为空的 200 OK 响应。

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-10-21T17:26:28Z",
      "title": "ApiName"
   },
   "paths": {
      "/s3": {
         "get": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200"
                  }
               },
               "requestParameters": {
                  "integration.request.path.key": "method.request.querystring.key"
               },
               "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "GET",
               "type": "aws"
            }
         },
         "put": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     },
                     "application/octet-stream": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200"
                  }
               },
               "requestParameters": {
                  "integration.request.path.key": "method.request.querystring.key"
               },
               "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "PUT",
               "type": "aws",
               "contentHandling": "CONVERT_TO_BINARY"
            }
         }
      }
   },
   "x-amazon-apigateway-binary-media-types": [
      "application/octet-stream",
      "image/jpeg"
   ],
   "servers": [
      {
         "url": "https://abcdefghi.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/v1"
            }
         }
      }
   ],
   "components": {
      "schemas": {
         "Empty": {
            "type": "object",
            "title": "Empty Schema"
         }
      }
   }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-10-21T17:26:28Z",
    "title": "ApiName"
  },
  "host": "abcdefghi.execute-api.us-east-1.amazonaws.com",
  "basePath": "/v1",
  "schemes": [
    "https"
  ],
  "paths": {
    "/s3": {
      "get": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200"            }
          },
          "requestParameters": {
            "integration.request.path.key": "method.request.querystring.key"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "GET",
          "type": "aws"
        }
      },
      "put": {
        "produces": [
          "application/json", "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.path.key": "method.request.querystring.key"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "PUT",
          "type": "aws",
          "contentHandling" : "CONVERT_TO_BINARY"
        }
      }
    }
  },
  "x-amazon-apigateway-binary-media-types" : ["application/octet-stream", "image/jpeg"],
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

------

## 从 Amazon S3 下载图像
<a name="api-gateway-content-encodings-example-download-image-from-s3"></a>

从 Amazon S3 下载二进制 blob 形式的图像文件 (`image.jpg`)：

```
GET /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/octet-stream
```

成功的响应类似于以下示例：

```
200 OK HTTP/1.1

[raw bytes]
```

因为 `Accept` 标头设置为二进制媒体类型 `application/octet-stream`，并且您对 API 启用了二进制支持，所以返回原始字节。

要从 Amazon S3 下载采用 JSON 属性格式的 Base64 编码字符串形式的图像文件 (`image.jpg`)，请向 200 集成响应添加一个响应模板，如以下粗体 OpenAPI 定义块所示：

```
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "{\n   \"image\": \"$input.body\"\n}"
              }
            }
          },
```

下载图像文件的请求如下所示：

```
GET /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json
```

成功响应如下所示：

```
200 OK HTTP/1.1

{
  "image": "W3JhdyBieXRlc10="
}
```

## 将图像上传到 Amazon S3
<a name="api-gateway-content-encodings-example-upload-image-to-s3"></a>

将二进制 blob 形式的图像文件 (`image.jpg`) 上传到 Amazon S3：

```
PUT /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/octet-stream
Accept: application/json

[raw bytes]
```

成功响应如下所示：

```
200 OK HTTP/1.1        
```

将 Base64 编码字符串形式的图像文件 (`image.jpg`) 上传到 Amazon S3：

```
PUT /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json

W3JhdyBieXRlc10=
```

输入负载必须是 Base64 编码的字符串，因为 `Content-Type` 标头值设置为 `application/json`。成功响应如下所示：

```
200 OK HTTP/1.1
```

# 使用 API Gateway API 访问 Lambda 中的二进制文件
<a name="api-gateway-content-encodings-examples-image-lambda"></a>

以下 OpenAPI 示例展示了如何通过 API Gateway API 访问 AWS Lambda 中的二进制文件。此 API 公开了用于下载和上传指定图像文件的 `GET /lambda?key={file-name}` 和 `PUT /lambda?key={file-name}` 方法。`GET` 方法按照所提供的映射模板，在一个 200 OK 响应中返回 Base64 编码字符串形式的图像文件作为 JSON 输出的一部分。`PUT` 方法将原始二进制 blob 作为输入，并返回一个负载为空的 200 OK 响应。

您创建 API 调用的 Lambda 函数，该函数必须返回 `Content-Type` 标头为 `application/json` 的 base64 编码字符串。

**Topics**
+ [用于访问 Lambda 中图像的示例 API 的 OpenAPI 文件](#api-gateway-content-encodings-example-image-lambda-swagger-file)
+ [从 Lambda 下载图像](#api-gateway-content-encodings-example-download-image-from-lambda)
+ [将图像上传到 Lambda](#api-gateway-content-encodings-example-upload-image-to-lambda)

## 用于访问 Lambda 中图像的示例 API 的 OpenAPI 文件
<a name="api-gateway-content-encodings-example-image-lambda-swagger-file"></a>

以下 OpenAPI 文件显示了一个 API 示例，阐明了如何从 Lambda 下载图像文件以及如何将图像文件上传到 Lambda。

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-10-21T17:26:28Z",
      "title": "ApiName"
   },
   "paths": {
      "/lambda": {
         "get": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
               "type": "AWS",
               "credentials": "arn:aws:iam::123456789012:role/Lambda",
               "httpMethod": "POST",
               "requestTemplates": {
                  "application/json": "{\n   \"imageKey\": \"$input.params('key')\"\n}"
               },
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200",
                     "responseTemplates": {
                        "application/json": "{\n   \"image\": \"$input.body\"\n}"
                     }
                  }
               }
            }
         },
         "put": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     },
                     "application/octet-stream": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
               "type": "AWS",
               "credentials": "arn:aws:iam::123456789012:role/Lambda",
               "httpMethod": "POST",
               "contentHandling": "CONVERT_TO_TEXT",
               "requestTemplates": {
                  "application/json": "{\n   \"imageKey\": \"$input.params('key')\", \"image\": \"$input.body\"\n}"
               },
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200"
                  }
               }
            }
         }
      }
   },
   "x-amazon-apigateway-binary-media-types": [
      "application/octet-stream",
      "image/jpeg"
   ],
   "servers": [
      {
         "url": "https://abcdefghi.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/v1"
            }
         }
      }
   ],
   "components": {
      "schemas": {
         "Empty": {
            "type": "object",
            "title": "Empty Schema"
         }
      }
   }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-10-21T17:26:28Z",
    "title": "ApiName"
  },
  "host": "abcdefghi.execute-api.us-east-1.amazonaws.com",
  "basePath": "/v1",
  "schemes": [
    "https"
  ],
  "paths": {
    "/lambda": {
      "get": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
          "type": "AWS",
          "credentials": "arn:aws:iam::123456789012:role/Lambda",
          "httpMethod": "POST",
          "requestTemplates": {
            "application/json": "{\n   \"imageKey\": \"$input.params('key')\"\n}"
          },
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "{\n   \"image\": \"$input.body\"\n}"
              }
            }
          }
        }
      },
      "put": {
        "produces": [
          "application/json", "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
          "type": "AWS",
          "credentials": "arn:aws:iam::123456789012:role/Lambda",
          "httpMethod": "POST",
          "contentHandling" : "CONVERT_TO_TEXT",
          "requestTemplates": {
            "application/json": "{\n   \"imageKey\": \"$input.params('key')\", \"image\": \"$input.body\"\n}"
          },
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200"
            }
          }
        }
      }
    }
  },
  "x-amazon-apigateway-binary-media-types" : ["application/octet-stream", "image/jpeg"],
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

------

## 从 Lambda 下载图像
<a name="api-gateway-content-encodings-example-download-image-from-lambda"></a>

从 Lambda 下载二进制 blob 形式的图像文件 (`image.jpg`)：

```
GET /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/octet-stream
```

成功响应如下所示：

```
200 OK HTTP/1.1

[raw bytes]
```

从 Lambda 下载 Base64 编码字符串（格式化为 JSON 属性）形式的图像文件 (`image.jpg`)：

```
GET /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json
```

成功响应如下所示：

```
200 OK HTTP/1.1

{
  "image": "W3JhdyBieXRlc10="
}
```

## 将图像上传到 Lambda
<a name="api-gateway-content-encodings-example-upload-image-to-lambda"></a>

将二进制 blob 形式的图像文件 (`image.jpg`) 上传到 Lambda：

```
PUT /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/octet-stream
Accept: application/json

[raw bytes]
```

成功响应如下所示：

```
200 OK            
```

将 Base64 编码字符串形式的图像文件 (`image.jpg`) 上传到 Lambda：

```
PUT /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json

W3JhdyBieXRlc10=
```

成功响应如下所示：

```
200 OK           
```

# 调用 API Gateway 中的 REST API
<a name="how-to-call-api"></a>

为调用已部署的 API，客户端需要向 API Gateway 组件服务的 URL 提交请求以完成 API 执行（称为 `execute-api`）。

REST API 的基本 URL 采用以下格式：

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

其中，*api-id* 是 API 标识符，*region* 是 AWS 区域，*stage* 是 API 部署的阶段名称。

**重要**  
在可以调用 API 之前，必须将其部署在 API Gateway 中。有关部署 API 的说明，请参阅[在 API Gateway 中部署 REST API。](how-to-deploy-api.md)。

**Topics**
+ [获取 API 的调用 URL](#apigateway-how-to-call-rest-api)
+ [调用 API](#apigateway-call-api)
+ [使用 API Gateway 控制台测试 REST API 方法](how-to-test-method.md)
+ [使用由 API Gateway 为 REST API 生成的 Java 开发工具包](how-to-call-apigateway-generated-java-sdk.md)
+ [使用由 API Gateway 为 REST API 生成的 Android 开发工具包](how-to-generate-sdk-android.md)
+ [使用由 API Gateway 为 REST API 生成的 JavaScript 开发工具包](how-to-generate-sdk-javascript.md)
+ [使用由 API Gateway 为 REST API 生成的 Ruby 开发工具包](how-to-call-sdk-ruby.md)
+ [在 Objective-C 或 Swift 中使用由 API Gateway 为 REST API 生成的 iOS 开发工具包](how-to-generate-sdk-ios.md)

## 获取 API 的调用 URL
<a name="apigateway-how-to-call-rest-api"></a>

您可以使用控制台、AWS CLI 或导出的 OpenAPI 定义来获取 API 的调用 URL。

### 使用控制台获取 API 的调用 URL
<a name="apigateway-obtain-url-console"></a>

以下过程介绍了如何在 REST API 控制台中获取 API 的调用 URL。

**使用 REST API 控制台获取 API 的调用 URL**

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

1. 选择已部署的 API。

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

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

   此 URL 用于您的 API 的根资源。  
![\[创建 REST API 后，控制台会显示 API 的调用 URL。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/getting-started-rest-invoke-url.png)

1. 要获取 API 中其它资源的 API 的调用 URL，请在二级导航窗格下展开此阶段，然后选择一个方法。

1. 选择复制图标来复制 API 的资源级调用 URL。  
![\[您的 REST API 的资源级别 URL 位于阶段的二级导航窗格下方。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/resource-level-invoke-url.png)

#### 使用 AWS CLI 获取 API 的调用 URL
<a name="apigateway-obtain-url-cli"></a>

以下过程介绍了如何使用 AWS CLI 获取 API 的调用 URL。

**使用 AWS CLI 获取 API 的调用 URL**

1. 使用以下命令来获取 `rest-api-id`。此命令返回您的区域中的所有 `rest-api-id` 值。有关更多信息，请参阅 [get-rest-apis](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-rest-apis.html)。

   ```
   aws apigateway get-rest-apis
   ```

1. 将示例 `rest-api-id` 替换为您的 `rest-api-id`，将示例 *\$1stage-name\$1* 替换为您的 *\$1stage-name\$1*，将 *\$1region\$1* 替换为您的区域。

   ```
   https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}/
   ```

##### 使用 API 的已导出 OpenAPI 定义文件获取 API 的调用 URL
<a name="apigateway-obtain-url-openapi"></a>

此外，您也可以构造根 URL，方法是组合 API 的已导出 OpenAPI 定义文件的 `host` 和 `basePath` 字段。有关如何导出 API 的说明，请参阅[从 API Gateway 导出 REST API](api-gateway-export-api.md)。

## 调用 API
<a name="apigateway-call-api"></a>

您可以使用浏览器、curl 或其它应用程序（例如 [Postman](https://www.postman.com/)）调用已部署的 API。

此外，您可以使用 API Gateway 控制台测试 API 调用。测试使用 API Gateway 的 `TestInvoke` 特征，该特征允许在部署 API 之前对 API 进行测试。有关更多信息，请参阅 [使用 API Gateway 控制台测试 REST API 方法](how-to-test-method.md)。

**注意**  
调用 URL 中的查询字符串参数值不得包含 `%%`。

### 使用 Web 浏览器调用 API
<a name="apigateway-call-api-brower"></a>

如果 API 允许匿名访问，您可以使用任何 Web 浏览器来调用任何 `GET` 方法。在浏览器的地址栏中输入完整的调用 URL。

对于其它方法或任何要求身份验证的调用，您必须指定负载或签署请求。您可以在 HTML 页面背后的脚本中，或者在使用 AWS 开发工具包之一的客户端应用程序中处理这些调用。

#### 使用 curl 调用 API
<a name="apigateway-call-api-curl"></a>

您可以在终端中使用像 [curl](https://curl.se/) 这样的工具来调用 API。以下示例 curl 命令在 API 的 `prod` 阶段的 `getUsers` 资源上调用 GET 方法。

------
#### [ Linux or Macintosh ]

```
curl -X GET 'https://b123abcde4.execute-api.us-west-2.amazonaws.com/prod/getUsers'
```

------
#### [ Windows ]

```
curl -X GET "https://b123abcde4.execute-api.us-west-2.amazonaws.com/prod/getUsers"
```

------

# 使用 API Gateway 控制台测试 REST API 方法
<a name="how-to-test-method"></a>

使用 API Gateway 控制台测试 REST API 方法。

**Topics**
+ [先决条件](#how-to-test-method-prerequisites)
+ [使用 API Gateway 控制台测试方法](#how-to-test-method-console)

## 先决条件
<a name="how-to-test-method-prerequisites"></a>
+ 您必须指定要测试的方法的设置。按照[API Gateway 中用于 REST API 的方法](how-to-method-settings.md)中的说明进行操作。

## 使用 API Gateway 控制台测试方法
<a name="how-to-test-method-console"></a>

**重要**  
使用 API Gateway 控制台测试方法可能会导致对资源进行无法撤销的更改。使用 API Gateway 控制台测试方法与在 API Gateway 控制台之外调用方法相同。例如，如果您使用 API Gateway 控制台调用用于删除 API 资源的方法，并且方法调用成功，那么将删除 API 资源。

**测试方法**

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

1. 选择一个 REST API。

1. 在**资源**窗格中，选择要测试的方法。

1. 选择**测试**选项卡。您可能需要选择右箭头按钮，以显示该选项卡。  
![\[使用“测试”选项卡来测试您的 API。它位于”方法响应”选项卡旁边。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/api-gateway-test-new-console.png)

    在任何显示的框中输入值（例如**查询字符串**、**标头**和**请求正文**。控制台会以默认 application/json 形式将这些值包括在方法请求中。

   对于您可能需要指定的其它选项，请联系 API 所有者。

1. 选择**测试**。此时将显示以下信息：
   + **请求**是为方法调用的资源路径。
   + **状态**是响应的 HTTP 状态代码。
   + **延迟（毫秒）**是收到调用方请求和返回响应之间的时间。
   + **响应正文**是 HTTP 响应正文。
   + **响应标头**是 HTTP 响应标头。
**提示**  
根据映射的不同，HTTP 状态代码、响应正文和响应标头可能不同于从 Lambda 函数、HTTP 代理或 AWS 服务代理发送的内容。
   + **日志** 是模拟的 Amazon CloudWatch Logs 条目，如果在 API Gateway 控制台之外调用此方法，则会写入这些条目。
**注意**  
尽管 CloudWatch Logs 条目是模拟的，但方法调用的结果是真实的。

 除了使用 API Gateway 控制台之外，您还可以使用 AWS CLI 或适用于 API Gateway 的 AWS 开发工具包来测试调用方法。要使用 AWS CLI 执行此操作，请参阅 [test-invoke-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/test-invoke-method.html)。

# 使用由 API Gateway 为 REST API 生成的 Java 开发工具包
<a name="how-to-call-apigateway-generated-java-sdk"></a>

在此部分中，我们将使用[简单结算器](simple-calc-lambda-api-swagger-definition.md) API 作为示例，概述使用由 API Gateway 为 REST API 生成的 Java 开发工具包的步骤。您必须先完成[为 API Gateway 中的 REST API 生成 SDK](how-to-generate-sdk.md)中的步骤，然后才能继续操作。

**安装和使用 API Gateway 生成的 Java 开发工具包**

1. 提取您之前下载的 API Gateway 生成的 .zip 文件中的内容。

1. 下载并安装 [Apache Maven](https://maven.apache.org/)（必须为版本 3.5 或更高版本）。

1. 下载并安装 [JDK 8](https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html)。

1. 设置 `JAVA_HOME` 环境变量。

1.  转到 pom.xml 文件所在的解压缩的开发工具包文件夹。默认情况下，此文件夹为 `generated-code`。运行 **mvn install** 命令，将编译的构件文件安装到您的本地 Maven 存储库中。这将创建包含编译的开发工具包库的 `target` 文件夹。

1.  在空目录中输入以下命令来创建客户端项目存根，以使用已安装的开发工具包库来调用 API。

   ```
   mvn -B archetype:generate \
       -DarchetypeGroupdId=org.apache.maven.archetypes \
       -DgroupId=examples.aws.apig.simpleCalc.sdk.app \
       -DartifactId=SimpleCalc-sdkClient
   ```
**注意**  
 为提高可读性，在上述命令中添加了分隔符 `\`。整个命令应在一行中且不带分隔符。

    此命令会创建一个应用程序存根。应用程序存根在项目的根目录（上述命令中的 *SimpleCalc-sdkClient*）下包含一个 `pom.xml` 文件和一个 `src` 文件夹。最初，有两个源文件：`src/main/java/{package-path}/App.java` 和 `src/test/java/{package-path}/AppTest.java`。在本示例中，*\$1package-path\$1* 为 `examples/aws/apig/simpleCalc/sdk/app`。此程序包路径源自 `DarchetypeGroupdId` 值。您可以使用 `App.java` 文件作为您的客户端应用程序模板，并且可以根据需要在同一文件夹中添加其他文件。您可以使用 `AppTest.java` 文件作为应用程序的单元测试模板，并且可以根据需要将其他测试代码文件添加到同一个测试文件夹中。

1. 在生成的 `pom.xml` 文件中将程序包依赖关系更新为以下内容，根据需要替换项目的 `groupId` `artifactId`、`version` 和 `name` 属性：

   ```
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>examples.aws.apig.simpleCalc.sdk.app</groupId>
     <artifactId>SimpleCalc-sdkClient</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>SimpleCalc-sdkClient</name>
     <url>http://maven.apache.org</url>
   
      <dependencies>
         <dependency>
             <groupId>com.amazonaws</groupId>
             <artifactId>aws-java-sdk-core</artifactId>
             <version>1.11.94</version>
         </dependency>
         <dependency>
             <groupId>my-apig-api-examples</groupId>
             <artifactId>simple-calc-sdk</artifactId>
             <version>1.0.0</version>
         </dependency>
         
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
       </dependency>
   
       <dependency>
           <groupId>commons-io</groupId>
           <artifactId>commons-io</artifactId>
           <version>2.5</version>
       </dependency>    
     </dependencies>
   
     <build>
       <plugins>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.5.1</version>
           <configuration>
             <source>1.8</source>
             <target>1.8</target>
           </configuration>
         </plugin>
       </plugins>
     </build>
   </project>
   ```
**注意**  
 当 `aws-java-sdk-core` 从属构件的较新版本与以上指定的版本 (`1.11.94`) 不兼容时，您必须将 `<version>` 标记更新到新版本。

1.  接下来，我们将介绍如何通过调用开发工具包的 `getABOp(GetABOpRequest req)`、`getApiRoot(GetApiRootRequest req)` 和 `postApiRoot(PostApiRootRequest req)` 方法，来使用开发工具包调用 API。这些方法分别与 `GET /{a}/{b}/{op}`、`GET /?a={x}&b={y}&op={operator}` 和 `POST /` 方法对应，具有 `{"a": x, "b": y, "op": "operator"}` API 请求的负载。

    按如下所示更新 `App.java` 文件：

   ```
   package examples.aws.apig.simpleCalc.sdk.app;
   
   import java.io.IOException;
   
   import com.amazonaws.opensdk.config.ConnectionConfiguration;
   import com.amazonaws.opensdk.config.TimeoutConfiguration;
   
   import examples.aws.apig.simpleCalc.sdk.*;
   import examples.aws.apig.simpleCalc.sdk.model.*;
   import examples.aws.apig.simpleCalc.sdk.SimpleCalcSdk.*;
   
   public class App 
   {
       SimpleCalcSdk sdkClient;
   
       public App() {
           initSdk();
       }
   
       // The configuration settings are for illustration purposes and may not be a recommended best practice.
       private void initSdk() {
           sdkClient = SimpleCalcSdk.builder()
                 .connectionConfiguration(
                     new ConnectionConfiguration()
                           .maxConnections(100)
                           .connectionMaxIdleMillis(1000))
                 .timeoutConfiguration(
                     new TimeoutConfiguration()
                           .httpRequestTimeout(3000)
                           .totalExecutionTimeout(10000)
                           .socketTimeout(2000))
           .build();
   
       }
       // Calling shutdown is not necessary unless you want to exert explicit control of this resource.
       public void shutdown() {
           sdkClient.shutdown();
       }
        
       // GetABOpResult getABOp(GetABOpRequest getABOpRequest)
       public Output getResultWithPathParameters(String x, String y, String operator) {
       	operator = operator.equals("+") ? "add" : operator;
       	operator = operator.equals("/") ? "div" : operator; 
   
           GetABOpResult abopResult = sdkClient.getABOp(new GetABOpRequest().a(x).b(y).op(operator));
           return abopResult.getResult().getOutput();
       }
   
       public Output getResultWithQueryParameters(String a, String b, String op) {
           GetApiRootResult rootResult = sdkClient.getApiRoot(new GetApiRootRequest().a(a).b(b).op(op));
           return rootResult.getResult().getOutput();
       }
   
       public Output getResultByPostInputBody(Double x, Double y, String o) {
       	PostApiRootResult postResult = sdkClient.postApiRoot(
       		new PostApiRootRequest().input(new Input().a(x).b(y).op(o)));
       	return postResult.getResult().getOutput();
       }
   
       public static void main( String[] args )
       {
           System.out.println( "Simple calc" );
           // to begin
           App calc = new App();
           
           // call the SimpleCalc API
           Output res = calc.getResultWithPathParameters("1", "2", "-");
           System.out.printf("GET /1/2/-: %s\n", res.getC());
   
           // Use the type query parameter
           res = calc.getResultWithQueryParameters("1", "2", "+");
           System.out.printf("GET /?a=1&b=2&op=+: %s\n", res.getC());
   
           // Call POST with an Input body.
           res = calc.getResultByPostInputBody(1.0, 2.0, "*");
           System.out.printf("PUT /\n\n{\"a\":1, \"b\":2,\"op\":\"*\"}\n %s\n", res.getC());
   
           
       }
   }
   ```

    在上述示例中，用于实例化开发工具包客户端的配置设置用于说明用途，并不一定是建议的最佳实践。此外，调用 `sdkClient.shutdown()` 是可选的，尤其是在您需要精确控制何时释放资源的情况下。

 我们已介绍使用 Java 开发工具包调用 API 的基本模式。您可以扩展说明以调用其他 API 方法。

# 使用由 API Gateway 为 REST API 生成的 Android 开发工具包
<a name="how-to-generate-sdk-android"></a>

在本部分中，我们介绍由 API Gateway 为 REST API 生成的 Android 开发工具包的使用步骤。您必须先完成[为 API Gateway 中的 REST API 生成 SDK](how-to-generate-sdk.md)中的步骤，然后才能继续进行操作。

**注意**  
 生成的开发工具包与 Android 4.4 及更早版本不兼容。有关更多信息，请参阅 [Amazon API Gateway 重要说明](api-gateway-known-issues.md)。

**安装和使用由 API Gateway 生成的 Android 开发工具包**

1. 提取您之前下载的 API Gateway 生成的 .zip 文件中的内容。

1. 下载并安装 [Apache Maven](https://maven.apache.org/)（最好是版本 3.x）。

1. 下载并安装 [JDK 8](https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html)。

1. 设置 `JAVA_HOME` 环境变量。

1. 运行 **mvn install** 命令，将编译的构件文件安装到您的本地 Maven 存储库中。这将创建包含编译的开发工具包库的 `target` 文件夹。

1. 将 `target` 文件夹中的开发工具包文件（其名称源自您在生成开发工具包时指定的 **Artifact Id** 和 **Artifact Version**，如 `simple-calcsdk-1.0.0.jar`），以及 `target/lib` 文件夹中的所有文件夹库复制到项目的 `lib` 文件夹中。

   如果您使用的是 Android Studio，请在客户端应用程序模块下创建一个 `libs` 文件夹，并将所需的 .jar 文件复制到此文件夹中。验证该模块的 Gradle 文件中的依赖项部分是否包含以下内容。

   ```
       compile fileTree(include: ['*.jar'], dir: 'libs')
       compile fileTree(include: ['*.jar'], dir: 'app/libs')
   ```

   确保没有声明重复的 .jar 文件。

1. 使用 `ApiClientFactory` 类初始化 API Gateway 生成的开发工具包。例如：

   ```
   ApiClientFactory factory = new ApiClientFactory();
   
   // Create an instance of your SDK. Here, 'SimpleCalcClient.java' is the compiled java class for the SDK generated by API Gateway. 
   final SimpleCalcClient client = factory.build(SimpleCalcClient.class);
   
   // Invoke a method: 
   //   For the 'GET /?a=1&b=2&op=+' method exposed by the API, you can invoke it by calling the following SDK method:
   
   Result output = client.rootGet("1", "2", "+");
   
   //     where the Result class of the SDK corresponds to the Result model of the API.
   //
   
   //   For the 'GET /{a}/{b}/{op}'  method exposed by the API, you can call the following SDK method to invoke the request,
   
   Result output = client.aBOpGet(a, b, c);
   
   //     where a, b, c can be "1", "2", "add", respectively.
   
   //   For the following API method:
   //        POST /
   //        host: ...
   //        Content-Type: application/json
   //    
   //        { "a": 1, "b": 2, "op": "+" }
   // you can call invoke it by calling the rootPost method of the SDK as follows:
   Input body = new Input();
   input.a=1;
   input.b=2;
   input.op="+";
   Result output = client.rootPost(body);
   
   //      where the Input class of the SDK corresponds to the Input model of the API.
   
   // Parse the result:
   //     If the 'Result' object is { "a": 1, "b": 2, "op": "add", "c":3"}, you retrieve the result 'c') as 
   
   String result=output.c;
   ```

1. 要使用 Amazon Cognito 凭证提供程序授权调用您的 API，请通过 API Gateway 生成的开发工具包使用 `ApiClientFactory` 类传递一组 AWS 凭证，如下例所示。

   ```
   // Use CognitoCachingCredentialsProvider to provide AWS credentials
   // for the ApiClientFactory
   AWSCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
           context,          // activity context
           "identityPoolId", // Cognito identity pool id
           Regions.US_EAST_1 // region of Cognito identity pool
   );
   
   ApiClientFactory factory = new ApiClientFactory()
     .credentialsProvider(credentialsProvider);
   ```

1. 要使用 API Gateway 生成的开发工具包设置 API 键，请使用与以下示例类似的代码。

   ```
   ApiClientFactory factory = new ApiClientFactory()
     .apiKey("YOUR_API_KEY");
   ```

# 使用由 API Gateway 为 REST API 生成的 JavaScript 开发工具包
<a name="how-to-generate-sdk-javascript"></a>

以下过程介绍如何使用 API Gateway 生成的 JavaScript SDK。

**注意**  
这些说明假设您已完成[为 API Gateway 中的 REST API 生成 SDK](how-to-generate-sdk.md)中的说明。

**重要**  
如果您的 API 仅定义了 ANY 方法，则生成的开发工具包将不会包含 `apigClient.js` 文件，您将需要自己定义 ANY 方法。

**要安装，请启动并调用由 API Gateway 为 REST API 生成的 JavaScript 开发工具包**

1. 提取您之前下载的 API Gateway 生成的 .zip 文件中的内容。

1. 针对 API Gateway 生成的开发工具包将调用的所有方法启用跨源资源共享 (CORS)。有关说明，请参阅 [针对 API Gateway 中的 REST API 的 CORS](how-to-cors.md)。

1. 在您的网页中，添加对以下脚本的引用。

   ```
   <script type="text/javascript" src="lib/axios/dist/axios.standalone.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/rollups/hmac-sha256.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/rollups/sha256.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/components/hmac.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/components/enc-base64.js"></script>
   <script type="text/javascript" src="lib/url-template/url-template.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/sigV4Client.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/apiGatewayClient.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/simpleHttpClient.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/utils.js"></script>
   <script type="text/javascript" src="apigClient.js"></script>
   ```

1. 在代码中，使用类似于以下内容的代码初始化 API Gateway 生成的开发工具包。

   ```
   var apigClient = apigClientFactory.newClient();
   ```

   要使用 AWS 凭证初始化 API Gateway 生成的开发工具包，请使用类似于以下内容的代码。如果您使用 AWS 凭证，系统将签署针对 API 的所有请求。

   ```
   var apigClient = apigClientFactory.newClient({
     accessKey: 'ACCESS_KEY',
     secretKey: 'SECRET_KEY',
   });
   ```

   要将 API 密钥用于 API Gateway 生成的开发工具包，您可以使用类似于以下内容的代码，将 API 密钥作为参数传递给 `Factory` 对象。如果您使用 API 密钥，它将被指定为 `x-api-key` 标头的一部分，并且系统将签署针对 API 的所有请求。这意味着您必须为每个请求设置相应的 CORS Accept 标头。

   ```
   var apigClient = apigClientFactory.newClient({
     apiKey: 'API_KEY'
   });
   ```

   

1. 使用类似于以下内容的代码调用 API Gateway 中的 API 方法。每次调用都会返回成功和失败回调的承诺。

   ```
   var params = {
     // This is where any modeled request parameters should be added.
     // The key is the parameter name, as it is defined in the API in API Gateway.
     param0: '',
     param1: ''
   };
   
   var body = {
     // This is where you define the body of the request,
   };
   
   var additionalParams = {
     // If there are any unmodeled query parameters or headers that must be
     //   sent with the request, add them here.
     headers: {
       param0: '',
       param1: ''
     },
     queryParams: {
       param0: '',
       param1: ''
     }
   };
   
   apigClient.methodName(params, body, additionalParams)
       .then(function(result){
         // Add success callback code here.
       }).catch( function(result){
         // Add error callback code here.
       });
   ```

   此处，*methodName* 由方法请求的资源路径和 HTTP 动词构成。对于 SimpleCalc API，API 方法的开发工具包方法为 

   ```
   1. GET /?a=...&b=...&op=...
   2. POST /
   
      { "a": ..., "b": ..., "op": ...}
   3. GET /{a}/{b}/{op}
   ```

   相应的开发工具包方法如下所示：

   ```
   1. rootGet(params);      // where params={"a": ..., "b": ..., "op": ...} is resolved to the query parameters
   2. rootPost(null, body); // where body={"a": ..., "b": ..., "op": ...}
   3. aBOpGet(params);      // where params={"a": ..., "b": ..., "op": ...} is resolved to the path parameters
   ```

   

# 使用由 API Gateway 为 REST API 生成的 Ruby 开发工具包
<a name="how-to-call-sdk-ruby"></a>

以下过程介绍如何使用 API Gateway 生成的 Ruby SDK。

**注意**  
这些说明假设您已完成[为 API Gateway 中的 REST API 生成 SDK](how-to-generate-sdk.md)中的说明。

**要开始安装，请实例化并调用由 API Gateway 为 REST API 生成的 Ruby 开发工具包**

1. 解压缩下载的 Ruby 开发工具包文件。生成的开发工具包源如下所示。  
![\[将下载的 Ruby 开发工具包文件解压缩到 Ruby 模块中\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/ruby-gem-of-generated-sdk-for-simplecalc.png)

   

1.  从生成的开发工具包源构建 Ruby Gem，在终端窗口中使用以下 shell 命令：

   ```
   # change to /simplecalc-sdk directory
   cd simplecalc-sdk
   
   # build the generated gem
   gem build simplecalc-sdk.gemspec
   ```

   在此之后，**simplecalc-sdk-1.0.0.gem** 变为可用状态。

1.  安装 gem：

   ```
   gem install simplecalc-sdk-1.0.0.gem
   ```

1.  创建客户端应用程序。在应用程序中实例化和初始化 Ruby 开发工具包客户端：

   ```
   require 'simplecalc-sdk'
   client = SimpleCalc::Client.new(
       http_wire_trace: true,
       retry_limit: 5,
       http_read_timeout: 50
   )
   ```

   如果 API 已经配置了 `AWS_IAM` 类型的授权，您可以在初始化期间提供 `accessKey` 和 `secretKey`，包括调用方的 AWS 凭证。

   ```
   require 'pet-sdk'
   client = Pet::Client.new(
       http_wire_trace: true,
       retry_limit: 5,
       http_read_timeout: 50,
       access_key_id: 'ACCESS_KEY',
       secret_access_key: 'SECRET_KEY'
   )
   ```

1.  在应用程序中通过开发工具包进行 API 调用。
**提示**  
 如果您不熟悉开发工具包方法调用约定，可以查看生成的开发工具包 `client.rb` 文件夹中的 `lib` 文件。该文件夹包含支持的各个 API 方法调用的文档。

   搜索支持的操作：

   ```
   # to show supported operations:
   puts client.operation_names
   ```

   这将生成以下显示内容，分别对应于 `GET /?a={.}&b={.}&op={.}`、`GET /{a}/{b}/{op}` 的 API 方法，以及 `POST /`，加上 `{a:"…", b:"…", op:"…"}` 格式的负载：

   ```
   [:get_api_root, :get_ab_op, :post_api_root]
   ```

   要调用 `GET /?a=1&b=2&op=+` API 方法，请调用以下 Ruby 开发工具包方法：

   ```
   resp = client.get_api_root({a:"1", b:"2", op:"+"})
   ```

   要使用 `POST /` 的负载调用 `{a: "1", b: "2", "op": "+"}` API 方法，请调用以下 Ruby 开发工具包方法：

   ```
   resp = client.post_api_root(input: {a:"1", b:"2", op:"+"})
   ```

   要调用 `GET /1/2/+` API 方法，请调用以下 Ruby 开发工具包方法：

   ```
   resp = client.get_ab_op({a:"1", b:"2", op:"+"})
   ```

   成功的开发工具包方法调用返回以下响应：

   ```
   resp : {
       result: {
           input: {
               a: 1,
               b: 2,
               op: "+"
           },
           output: {
               c: 3
           }
       }
   }
   ```

# 在 Objective-C 或 Swift 中使用由 API Gateway 为 REST API 生成的 iOS 开发工具包
<a name="how-to-generate-sdk-ios"></a>

在本教程中，我们将介绍如何在 Objective-C 或 Swift 应用程序中使用由 API Gateway 为 REST API 生成的 iOS 开发工具包来调用底层 API。我们将使用 [SimpleCalc API](simple-calc-lambda-api.md) 作为示例来说明以下主题：
+ 如何将所需的 AWS 移动开发工具包组件安装到您的 Xcode 项目中
+ 如何在调用 API 的方法前创建 API 客户端对象
+ 如何通过 API 客户端对象上相应的 SDK 方法调用 API 方法
+ 如何使用 SDK 的相应模型类来准备方法输入并分析其结果

**Topics**
+ [使用生成的 iOS 开发工具包 (Objective-C) 来调用 API](#how-to-use-sdk-ios-objc)
+ [使用生成的 iOS 开发工具包 (Swift) 来调用 API](#how-to-generate-sdk-ios-swift)

## 使用生成的 iOS 开发工具包 (Objective-C) 来调用 API
<a name="how-to-use-sdk-ios-objc"></a>

在开始以下过程之前，您必须完成[为 API Gateway 中的 REST API 生成 SDK](how-to-generate-sdk.md)中适用于 Objective-C 版 iOS 的步骤，并下载已生成的软件开发工具包的 .zip 文件。

### 在 Objective-C 项目中安装 AWS 移动开发工具包和 API Gateway 生成的 iOS 开发工具包
<a name="use-sdk-ios-objc-install-sdk"></a>

以下过程将介绍如何安装开发工具包。

**安装并使用 API Gateway 生成的 Objective-C 版 iOS 开发工具包**

1. 提取您之前下载的 API Gateway 生成的 .zip 文件中的内容。使用 [SimpleCalc API](simple-calc-lambda-api.md)，您可能需要将解压的软件开发工具包文件夹重命名为类似 **sdk\$1objc\$1simple\$1calc** 的名字。此开发工具包文件夹中有一个 `README.md` 文件和一个 `Podfile` 文件。`README.md` 文件包含介绍如何安装和使用开发工具包的说明。本教程将提供有关这些说明的详细信息。安装过程会利用 [CocoaPods](https://cocoapods.org) 导入必需的 API Gateway 库和其他依赖的AWS移动开发工具包组件。您必须更新 `Podfile`，才能将开发工具包导入应用程序的 Xcode 项目中。解档开发工具包文件夹还包含一个 `generated-src` 文件夹，其中包含 API 已生成开发工具包的源代码。

1. 启动 Xcode，并创建一个新的 iOS Objective-C 项目。请记下该项目的目标。您需要在 `Podfile` 中对其进行设置。

      
![\[在 Xcode 中找到目标。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/use-sdk-in-ios-objc-project-find-target.png)

1. 要使用 CocoaPods 将 AWS Mobile SDK for iOS 导入 Xcode 项目中，请执行以下操作：

   1. 通过在终端窗口运行以下命令来安装 CocoaPods：

      ```
      sudo gem install cocoapods
      pod setup
      ```

   1. 将 `Podfile` 文件从提取的开发工具包文件夹复制到包含 Xcode 项目文件的同一目录。将以下代码块：

      ```
      target '<YourXcodeTarget>' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      替换为您的项目的目标名称：

      ```
      target 'app_objc_simple_calc' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      如果 Xcode 项目已经包含名为 `Podfile` 的文件，请向其添加以下代码行：

      ```
      pod 'AWSAPIGateway', '~> 2.4.7'
      ```

   1. 打开终端窗口，并运行以下命令：

      ```
      pod install
      ```

      这将安装 API Gateway 组件和其他依赖的 AWS 移动开发工具包组件。

   1. 关闭 Xcode 项目，然后打开 `.xcworkspace` 文件，以重新启动 Xcode。

   1. 将已提取开发工具包的 `.h` 目录中的所有 `.m` 和 `generated-src` 文件添加到 Xcode 项目中。

         
![\[.h 和 .m 文件位于 generated-src 中\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/use-sdk-in-ios-objc-project-add-sdk-src.png)

   要通过显式下载 AWS Mobile SDK for iOS 移动开发工具包或使用 AWSCarthage[ 的方式将 ](https://github.com/Carthage/Carthage#installing-carthage) Objective-C 导入您的项目中，请遵循 *README.md* 文件中的说明。确保只使用以下选项之一来导入 AWS 移动开发工具包。

### 在 Objective-C 项目中使用 API Gateway 生成的 iOS 开发工具包调用 API 方法
<a name="use-sdk-ios-objc-call-sdk"></a>

当您为此 [SimpleCalc API](simple-calc-lambda-api.md) 生成具有 `SIMPLE_CALC` 前缀的开发工具包，并将两个模型用于方法的输入 (`Input`) 和输出 (`Result`) 时，在开发工具包中，由此产生的 API 客户端类将变成 `SIMPLE_CALCSimpleCalcClient`，而且相应数据类分别是 `SIMPLE_CALCInput` 和 `SIMPLE_CALCResult`。API 请求和响应映射到开发工具包方法，如下所示：
+ 以下 API 请求

  ```
  GET /?a=...&b=...&op=...
  ```

  将变为以下开发工具包方法

  ```
  (AWSTask *)rootGet:(NSString *)op a:(NSString *)a b:(NSString *)b
  ```

  `AWSTask.result` 属性的类型是 `SIMPLE_CALCResult`，前提是 `Result` 模型已添加到该方法响应中。否则，属性的类型将是 `NSDictionary`。
+ 以下 API 请求

  ```
  POST /
      
  {
     "a": "Number",
     "b": "Number",
     "op": "String"
  }
  ```

  将变为以下开发工具包方法

  ```
  (AWSTask *)rootPost:(SIMPLE_CALCInput *)body
  ```
+ 以下 API 请求

  ```
  GET /{a}/{b}/{op}
  ```

  将变为以下开发工具包方法

  ```
  (AWSTask *)aBOpGet:(NSString *)a b:(NSString *)b op:(NSString *)op
  ```

以下过程将介绍如何在 Objective-C 应用程序源代码中调用 API 方法；例如，作为 `viewDidLoad` 文件中 `ViewController.m` 委派的一部分进行调用。

**通过 API Gateway 生成的 iOS 开发工具包调用 API**

1. 导入 API 客户端类标头文件，使 API 客户端类可在该应用程序内调用：

   ```
   #import "SIMPLE_CALCSimpleCalc.h"
   ```

   `#import` 语句还将为两个模型类导入 `SIMPLE_CALCInput.h` 和 `SIMPLE_CALCResult.h`。

1. 实例化 API 客户端类：

   ```
   SIMPLE_CALCSimpleCalcClient *apiInstance = [SIMPLE_CALCSimpleCalcClient defaultClient];
   ```

   要将 Amazon Cognito 和该 API 结合使用，请在默认的 `AWSServiceManager` 对象上设置 `defaultServiceConfiguration` 属性（如下所示），然后再调用 `defaultClient` 方法，以创建 API 客户端对象（如上一示例所示）：

   ```
   AWSCognitoCredentialsProvider *creds = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:your_cognito_pool_id];
   AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:creds];
   AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
   ```

1. 调用 `GET /?a=1&b=2&op=+` 方法以执行 `1+2`：

   ```
   [[apiInstance rootGet: @"+" a:@"1" b:@"2"] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
       _textField1.text = [self handleApiResponse:task];
       return nil;
   }];
   ```

   其中，帮助程序函数 `handleApiResponse:task` 会将结果格式设定为要在文本字段 (`_textField1`) 中显示的字符串。

   ```
   - (NSString *)handleApiResponse:(AWSTask *)task {
       if (task.error != nil) {
           return [NSString stringWithFormat: @"Error: %@", task.error.description];
       } else if (task.result != nil && [task.result isKindOfClass:[SIMPLE_CALCResult class]]) {
           return [NSString stringWithFormat:@"%@ %@ %@ = %@\n",task.result.input.a, task.result.input.op, task.result.input.b, task.result.output.c];
       }
       return nil;
   }
   ```

   最终显示为 `1 + 2 = 3`。

1. 使用负载调用 `POST /` 以执行 `1-2`：

   ```
   SIMPLE_CALCInput *input = [[SIMPLE_CALCInput alloc] init];
       input.a = [NSNumber numberWithInt:1];
       input.b = [NSNumber numberWithInt:2];
       input.op = @"-";
       [[apiInstance rootPost:input] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
           _textField2.text = [self handleApiResponse:task];
           return nil;
       }];
   ```

   最终显示为 `1 - 2 = -1`。

1. 调用 `GET /{a}/{b}/{op}` 以执行 `1/2`：

   ```
   [[apiInstance aBOpGet:@"1" b:@"2" op:@"div"] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
       _textField3.text = [self handleApiResponse:task];
       return nil;
   }];
   ```

   最终显示为 `1 div 2 = 0.5`。在这里，`div` 用于代替 `/`，因为后端的[简单 Lambda 函数](simple-calc-nodejs-lambda-function.md)不会处理 URL 编码的路径变量。

## 使用生成的 iOS 开发工具包 (Swift) 来调用 API
<a name="how-to-generate-sdk-ios-swift"></a>

在开始以下过程之前，您必须完成 [为 API Gateway 中的 REST API 生成 SDK](how-to-generate-sdk.md) 中适用于 Swift 版 iOS 的步骤，并下载已生成的开发工具包的 .zip 文件。

**Topics**
+ [在 Swift 项目中安装 AWS 移动开发工具包和 API Gateway 生成的开发工具包](#use-sdk-ios-swift-install-sdk)
+ [在 Swift 项目中通过 API Gateway 生成的 iOS 开发工具包调用 API 方法](#use-sdk-ios-swift-call-api)

### 在 Swift 项目中安装 AWS 移动开发工具包和 API Gateway 生成的开发工具包
<a name="use-sdk-ios-swift-install-sdk"></a>

以下过程将介绍如何安装开发工具包。

**安装并使用 API Gateway 生成的 Swift 版 iOS 开发工具包**

1. 提取您之前下载的 API Gateway 生成的 .zip 文件中的内容。使用 [SimpleCalc API](simple-calc-lambda-api.md)，您可能需要将解压的软件开发工具包文件夹重命名为类似 **sdk\$1swift\$1simple\$1calc** 的名字。此开发工具包文件夹中有一个 `README.md` 文件和一个 `Podfile` 文件。`README.md` 文件包含介绍如何安装和使用开发工具包的说明。本教程将提供有关这些说明的详细信息。安装过程会利用 [CocoaPods](https://cocoapods.org) 导入必需的 AWS 移动开发工具包组件。您必须更新 `Podfile`，才能将开发工具包导入 Swift 应用程序的 Xcode 项目中。解档开发工具包文件夹还包含一个 `generated-src` 文件夹，其中包含 API 已生成开发工具包的源代码。

1. 启动 Xcode，并创建一个新的 iOS Swift 项目。请记下该项目的目标。您需要在 `Podfile` 中对其进行设置。

      
![\[在 Xcode 中找到目标。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-find-target.png)

1. 要使用 CocoaPods 将必需的 AWS 移动开发工具包组件导入 Xcode 项目中，请执行以下操作：

   1. 如果 CocoaPods 还未安装，请在终端窗口中运行以下命令进行安装：

      ```
      sudo gem install cocoapods
      pod setup
      ```

   1. 将 `Podfile` 文件从提取的开发工具包文件夹复制到包含 Xcode 项目文件的同一目录。将以下代码块：

      ```
      target '<YourXcodeTarget>' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      替换为您的项目的目标名称，如下所示：

      ```
      target 'app_swift_simple_calc' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      如果 Xcode 项目已经包含带有正确目标的 `Podfile`，您只需将以下代码行添加到 `do ... end` 循环：

      ```
      pod 'AWSAPIGateway', '~> 2.4.7'
      ```

   1. 打开终端窗口，并在应用程序目录中运行以下命令：

      ```
      pod install
      ```

      这会将 API Gateway 组件及任何依赖的 AWS 移动开发工具包组件安装到应用程序的项目中。

   1. 关闭 Xcode 项目，然后打开 `*.xcworkspace` 文件，以重新启动 Xcode。

   1. 将已提取 `.h` 目录中所有开发工具包的标头文件 (`.swift`) 和 Swift 源代码文件 (`generated-src`) 添加到您的 Xcode 项目中。

         
![\[.h 和 .swift 文件位于 generated-src 中\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-add-sdk-src.png)

   1. 为了能够从 Swift 代码项目调用 AWS 移动开发工具包的 Objective-C 库，请在 Xcode 项目配置的 `Bridging_Header.h`Swift Compiler - General** 设置下，在 **Objective-C Bridging Header** 属性上设置 ** 文件路径：

         
![\[在“Swift 编译器 - 通用”下设置 Bridging_Header.h 文件路径。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-set-bridging-header.png)
**提示**  
您可以通过在 Xcode 的搜索框中键入 **bridging** 来找到 **Objective-C Bridging Header** 属性。

   1. 构建 Xcode 项目，以在继续进行操作之前验证它是否正确配置。如果与 AWS 移动开发工具包支持的 Swift 版本相比，您的 Xcode 使用了更新的版本，那么您将收到 Swift 编译器错误。在这种情况下，在 **Swift Compiler - Version** 设置下方将 **Use Legacy Swift Language Version (使用传统 Swift 语言版本)** 属性设置为**是**：

         
![\[将“旧版 Swift 语言版本”属性设置为“是”。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-set-legacy-swift-version.png)

   要通过显式下载AWS移动软件开发工具包或使用 [Carthage](https://github.com/Carthage/Carthage#installing-carthage)，将 Swift 中的AWS移动版 SDK for iOS 导入您的项目中，请按照开发工具包随附的 `README.md` 文件中的说明操作。确保只使用以下选项之一来导入 AWS 移动开发工具包。

### 在 Swift 项目中通过 API Gateway 生成的 iOS 开发工具包调用 API 方法
<a name="use-sdk-ios-swift-call-api"></a>

当您为此 [SimpleCalc API](simple-calc-lambda-api.md) 生成具有 `SIMPLE_CALC` 前缀的开发工具包，并通过两个模型描述 API 请求和响应的输入 (`Input`) 和输出 (`Result`) 时，在开发工具包中，由此产生的 API 客户端类将变成 `SIMPLE_CALCSimpleCalcClient`，而且相应数据类分别是 `SIMPLE_CALCInput` 和 `SIMPLE_CALCResult`。API 请求和响应映射到开发工具包方法，如下所示：
+ 以下 API 请求

  ```
  GET /?a=...&b=...&op=...
  ```

  将变为以下开发工具包方法

  ```
  public func rootGet(op: String?, a: String?, b: String?) -> AWSTask
  ```

  `AWSTask.result` 属性的类型是 `SIMPLE_CALCResult`，前提是 `Result` 模型已添加到该方法响应中。否则，它的类型将是 `NSDictionary`。
+ 以下 API 请求

  ```
  POST /
      
  {
     "a": "Number",
     "b": "Number",
     "op": "String"
  }
  ```

  将变为以下开发工具包方法

  ```
  public func rootPost(body: SIMPLE_CALCInput) -> AWSTask
  ```
+ 以下 API 请求

  ```
  GET /{a}/{b}/{op}
  ```

  将变为以下开发工具包方法

  ```
  public func aBOpGet(a: String, b: String, op: String) -> AWSTask
  ```

以下过程将介绍如何在 Swift 应用程序源代码中调用 API 方法；例如，作为 `viewDidLoad()` 文件中 `ViewController.m` 委派的一部分进行调用。

**通过 API Gateway 生成的 iOS 开发工具包调用 API**

1. 实例化 API 客户端类：

   ```
   let client = SIMPLE_CALCSimpleCalcClient.default()
   ```

   要将 Amazon Cognito 与 API 结合使用，请设置默认 AWS 服务配置（如下所示），然后再获取 `default` 方法（如之前所示）：

   ```
   let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityPoolId: "my_pool_id")        
   let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)        
   AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
   ```

1. 调用 `GET /?a=1&b=2&op=+` 方法以执行 `1+2`：

   ```
   client.rootGet("+", a: "1", b:"2").continueWithBlock {(task: AWSTask) -> AnyObject? in
       self.showResult(task)
       return nil
   }
   ```

   其中，帮助程序函数 `self.showResult(task)` 会将结果或错误打印到控制台；例如：

   ```
   func showResult(task: AWSTask) {
       if let error = task.error {
           print("Error: \(error)")
       } else if let result = task.result {
           if result is SIMPLE_CALCResult {
               let res = result as! SIMPLE_CALCResult
               print(String(format:"%@ %@ %@ = %@", res.input!.a!, res.input!.op!, res.input!.b!, res.output!.c!))
           } else if result is NSDictionary {
               let res = result as! NSDictionary
               print("NSDictionary: \(res)")
           }
       }
   }
   ```

   在生产应用程序中，您可以在文本字段中显示结果或错误。最终显示为 `1 + 2 = 3`。

1. 使用负载调用 `POST /` 以执行 `1-2`：

   ```
   let body = SIMPLE_CALCInput()
   body.a=1
   body.b=2
   body.op="-"
   client.rootPost(body).continueWithBlock {(task: AWSTask) -> AnyObject? in
       self.showResult(task)
       return nil
   }
   ```

   结果显示为 `1 - 2 = -1`。

1. 调用 `GET /{a}/{b}/{op}` 以执行 `1/2`：

   ```
   client.aBOpGet("1", b:"2", op:"div").continueWithBlock {(task: AWSTask) -> AnyObject? in
       self.showResult(task)
       return nil
   }
   ```

   最终显示为 `1 div 2 = 0.5`。在这里，`div` 用于代替 `/`，因为后端的[简单 Lambda 函数](simple-calc-nodejs-lambda-function.md)不会处理 URL 编码的路径变量。

# 在 API Gateway 中使用 OpenAPI 开发 REST API
<a name="api-gateway-import-api"></a>

您可以使用 API Gateway 将 REST API 从外部定义文件导入到 API Gateway。目前，API Gateway 支持 [OpenAPI v2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) 和 [OpenAPI v3.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.1.md) 定义文件，但[Amazon API Gateway 关于 REST API 的重要说明](api-gateway-known-issues.md#api-gateway-known-issues-rest-apis)中列出了例外。您可以使用新定义覆盖 API 以进行更新，还可以将定义与现有 API 合并。您使用 `mode` 查询参数指定请求 URL 中的选项。

有关从 API Gateway 控制台使用导入 API 功能的教程，请参阅 [教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

**Topics**
+ [将边缘优化的 API 导入 API Gateway](import-edge-optimized-api.md)
+ [将区域 API 导入到 API Gateway 中](import-export-api-endpoints.md)
+ [导入 OpenAPI 文件以更新现有 API 定义](api-gateway-import-api-update.md)
+ [设置 OpenAPI `basePath` 属性](api-gateway-import-api-basePath.md)
+ [用于 OpenAPI 导入的 AWS 变量](import-api-aws-variables.md)
+ [将 API 导入 API Gateway 时出现的错误和警告](api-gateway-import-api-errors-warnings.md)
+ [从 API Gateway 导出 REST API](api-gateway-export-api.md)

# 将边缘优化的 API 导入 API Gateway
<a name="import-edge-optimized-api"></a>

您可以导入 API 的 OpenAPI 定义文件，在 OpenAPI 文件之外通过指定 `EDGE` 端点类型作为导入操作的附加输入，创建新的边缘优化的 API。您可以使用 API Gateway 控制台、AWS CLI 或 AWS SDK 执行此操作。

有关从 API Gateway 控制台使用导入 API 特征的教程，请参阅 [教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

**Topics**
+ [使用 API Gateway 控制台导入边缘优化的 API](#import-edge-optimized-api-with-console)
+ [使用 AWS CLI 导入边缘优化的 API](#import-edge-optimized-api-with-awscli)

## 使用 API Gateway 控制台导入边缘优化的 API
<a name="import-edge-optimized-api-with-console"></a>

要使用 API Gateway 控制台导入边缘优化的 API，请执行以下操作：

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

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

1. 在**REST API**中，选择 **Import**（导入）。

1.  复制 API 的 OpenAPI 定义并将其粘贴到代码编辑器中，或者选择**选择文件**以从本地驱动器加载 OpenAPI 文件。

1.  对于 **API 端点类型**，选择**边缘优化**。

1.  选择**创建 API** 以开始导入 OpenAPI 定义。

## 使用 AWS CLI 导入边缘优化的 API
<a name="import-edge-optimized-api-with-awscli"></a>

以下 [import-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html) 命令从 OpenAPI 定义文件导入 API，以创建边缘优化的新 API：

```
aws apigateway import-rest-api \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```

或者使用到 `EDGE` 的 `endpointConfigurationTypes` 查询字符串参数的明确规范：

```
aws apigateway import-rest-api \
    --parameters endpointConfigurationTypes=EDGE \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```



# 将区域 API 导入到 API Gateway 中
<a name="import-export-api-endpoints"></a>

导入 API 时，您可以为 API 选择区域端点配置。您可以使用 API Gateway 控制台、AWS CLI 或 AWS SDK。

导出 API 时，API 端点配置不包括在导出的 API 定义中。

有关从 API Gateway 控制台使用导入 API 特征的教程，请参阅 [教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

**Topics**
+ [使用 API Gateway 控制台导入区域 API](#import-regional-api-with-console)
+ [使用 AWS CLI 导入区域 API](#import-regional-api-with-awscli)

## 使用 API Gateway 控制台导入区域 API
<a name="import-regional-api-with-console"></a>

要使用 API Gateway 控制台导入区域端点的 API，请执行以下操作：

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

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

1. 在**REST API**中，选择 **Import**（导入）。

1.  复制 API 的 OpenAPI 定义并将其粘贴到代码编辑器中，或者选择**选择文件**以从本地驱动器加载 OpenAPI 文件。

1. 对于 **API 端点类型**，选择**区域**。

1.  选择**创建 API** 以开始导入 OpenAPI 定义。

## 使用 AWS CLI 导入区域 API
<a name="import-regional-api-with-awscli"></a>

使用以下 [import-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html) 命令导入 OpenAPI 定义文件，并将端点类型设置为“区域”：

```
aws apigateway import-rest-api \
    --parameters endpointConfigurationTypes=REGIONAL \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```

# 导入 OpenAPI 文件以更新现有 API 定义
<a name="api-gateway-import-api-update"></a>

 您只能导入 API 定义来更新现有 API，无需更改其终端节点配置以及阶段或阶段变量，或者引用 API 密钥。

 导入到更新操作可以使用两种模式进行：合并和覆盖。

当一个 API (`A`) 合并到另一个 (`B`) 中时，如果两个 API 中没有互相冲突的定义，生成的 API 会保留 `A` 和 `B` 两者的定义。如果出现冲突，合并 API (`A`) 的方法定义会覆盖接受并入的 API (`B`) 的相应方法定义。例如，假设 `B` 声明了以下方法，用于返回 `200` 和 `206` 响应：

```
GET /a
POST /a
```

`A` 声明了以下方法，用于返回 `200` 和 `400` 响应：

```
GET /a
```

如果 `A` 并入 `B` 中，生成的 API 会生成以下方法：

```
GET /a
```

返回 `200` 和 `400` 响应，以及 

```
POST /a
```

返回 `200` 和 `206` 响应。

当您将外部 API 定义分解为多个较小的部分，并希望一次只应用其中一个部分的更改时，合并 API 非常有用。例如，如果多个团队负责一个 API 的不同部分并以不同的速度提供更改，则可能会出现此情况。在这种模式下，没有在导入的定义中明确定义的现有 API 中的项目会被忽略。

如果一个 API (`A`) 覆盖另一个 API (`B`)，生成的 API 将采纳覆盖方 API (`A`) 的定义。当外部 API 定义包含一个 API 的完整定义时，覆盖 API 非常有用。在这种模式下，没有在导入的定义中明确定义的现有 API 中的项目会被删除。

 要合并 API，请将一个 `PUT` 请求提交至 `https://apigateway.<region>.amazonaws.com/restapis/<restapi_id>?mode=merge`。`restapi_id` 路径参数值指定了将要与提供的 API 定义合并的 API。

 以下代码段显示了一个 `PUT` 请求的示例，该请求将作为负载的 JSON 格式的 OpenAPI API 定义与 API Gateway 中已指定的 API 合并。

```
PUT /restapis/<restapi_id>?mode=merge
Host:apigateway.<region>.amazonaws.com
Content-Type: application/json
Content-Length: ...

An OpenAPI API definition in JSON
```

 合并更新操作需要提取两个完整的 API 定义并将它们合并到一起。对于小型增量变更，您可以使用[资源更新](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateResource.html)操作。

 要覆盖 API，请将一个 `PUT` 请求提交至 `https://apigateway.<region>.amazonaws.com/restapis/<restapi_id>?mode=overwrite`。`restapi_id` 路径参数指定了将要被提供的 API 定义覆盖的 API。

 以下代码段显示了一个覆盖请求的示例，该请求的负载为 JSON 格式 OpenAPI 定义：

```
PUT /restapis/<restapi_id>?mode=overwrite
Host:apigateway.<region>.amazonaws.com
Content-Type: application/json
Content-Length: ...

An OpenAPI API definition in JSON
```

 如果未指定 `mode` 查询参数，则系统会假定合并。

**注意**  
 `PUT` 操作是幂等操作，不是原子操作。这意味着如果在处理过程中出现系统错误，则 API 可能会以不良状态结束。但是，重复该操作会成功将 API 置于相同的最终状态，如同第一次操作已成功一样。

# 设置 OpenAPI `basePath` 属性
<a name="api-gateway-import-api-basePath"></a>

在 [OpenAPI 2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) 中，您可以使用 `basePath` 属性来提供 `paths` 属性中定义的每个路径之前的一个或多个路径部分。由于 API Gateway 具有多种表达资源路径的方式，因此导入 API 功能可提供以下选项用于解释导入过程中的 `basePath` 属性：ignore、prepend 和 split。

在 [https://swagger.io/docs/specification/api-host-and-base-path/](https://swagger.io/docs/specification/api-host-and-base-path/) 中，`basePath` 不再是顶级属性。相反，作为惯例，API Gateway 使用[服务器变量](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#serverVariableObject)。导入 API 功能提供了相同选项用于解释导入过程中的基本路径。按如下所示标识基本路径：
+ 如果 API 不包含任何 `basePath` 变量，则导入 API 功能将检查 `server.url` 字符串以查看其是否包含 `"/"` 之外的路径。如果包含，则将该路径用作基本路径。
+ 如果 API 仅包含一个 `basePath` 变量，则导入 API 功能将使用其作为基本路径，即使该变量未在 `server.url` 中进行引用。
+ 如果 API 包含多个 `basePath` 变量，则导入 API 功能将仅使用第一个变量作为基本路径。

## 忽略
<a name="api-gateway-import-api-basePath-ignore"></a>

如果 OpenAPI 文件的 `basePath` 值为 `/a/b/c` 且 `paths` 属性包含 `/e` 和 `/f`，则以下 `POST` 或 `PUT` 请求：

```
POST /restapis?mode=import&basepath=ignore
```



```
PUT /restapis/api_id?basepath=ignore
```

 将在 API 中生成以下资源：
+ `/`
+ `/e`
+ `/f`

 效果是将 `basePath` 视为不存在，所有声明的 API 资源均相对于主机提供。例如，如果您有一个自定义域名，其 API 映射不包含*基础路径*和表示生产阶段的*阶段*值，则可以使用这一选项。

**注意**  
 API Gateway 自动为您创建一个根资源，即使该资源未在定义文件中明确声明。

 如未指定，`basePath` 以 `ignore` 为默认值。

## 前置
<a name="api-gateway-import-api-basePath-prepend"></a>

 如果 OpenAPI 文件的 `basePath` 值为 `/a/b/c` 且 `paths` 属性包含 `/e` 和 `/f`，则以下 `POST` 或 `PUT` 请求：

```
POST /restapis?mode=import&basepath=prepend
```



```
PUT /restapis/api_id?basepath=prepend
```

 将在 API 中生成以下资源：
+ `/`
+ `/a`
+ `/a/b`
+ `/a/b/c`
+ `/a/b/c/e`
+ `/a/b/c/f`

 效果是将 `basePath` 视为指定其他资源 (不含方法) 并将这些资源添加到声明的资源组中。例如，如果不同的团队负责一个 API 的不同部分且 `basePath` 可以为每个团队所负责 API 部分引用路径位置，则可以使用这一选项。

**注意**  
 API Gateway 自动为您创建中间资源，即使这些资源未在定义中明确声明。

## Split
<a name="api-gateway-import-api-basePath-split"></a>

 如果 OpenAPI 文件的 `basePath` 值为 `/a/b/c` 且 `paths` 属性包含 `/e` 和 `/f`，则以下 `POST` 或 `PUT` 请求：

```
POST /restapis?mode=import&basepath=split
```



```
PUT /restapis/api_id?basepath=split
```

 将在 API 中生成以下资源：
+ `/`
+ `/b`
+ `/b/c`
+ `/b/c/e`
+ `/b/c/f`

 效果是将最顶层的路径部分 `/a` 视为每个资源路径的开始，并在 API 自身内创建其他资源 (不含方法)。例如，如果 `a` 是一个您想在 API 中使用的阶段名称，则可以使用这一选项。

# 用于 OpenAPI 导入的 AWS 变量
<a name="import-api-aws-variables"></a>

您可以在 OpenAPI 定义中使用以下 AWS 变量。API Gateway 在导入 API 时解析变量。要指定变量，请使用 `${variable-name}`。下表介绍了可用的 AWS 变量。


| 变量名称 | 描述 | 
| --- | --- | 
| AWS::AccountId | 导入 API 的 AWS 账户 ID。例如，123456789012。 | 
| AWS::Partition | 在其中导入 API 的 AWS 分区。对于标准 AWS 区域，分区是 aws。 | 
| AWS::Region | 在其中导入 API 的 AWS 区域。例如，us-east-2。 | 

## AWS 变量示例
<a name="import-api-aws-variables-example"></a>

以下示例使用 AWS 变量为集成指定 AWS Lambda 函数。

------
#### [ OpenAPI 3.0 ]

```
openapi: "3.0.1"
info:
  title: "tasks-api"
  version: "v1.0"
paths:
  /:
    get:
      summary: List tasks
      description: Returns a list of tasks
      responses:
        200:
          description: "OK"
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Task"
        500:
          description: "Internal Server Error"
          content: {}
      x-amazon-apigateway-integration:
        uri:
          arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaFunctionName/invocations
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"
components:
  schemas:
    Task:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
```

------

# 将 API 导入 API Gateway 时出现的错误和警告
<a name="api-gateway-import-api-errors-warnings"></a>

在将外部定义文件导入 API Gateway 时，API Gateway 可能会生成警告和错误。以下部分讨论导入过程中可能出现的错误和警告。

## 导入过程中出现错误
<a name="api-gateway-import-api-errors"></a>

 在导入过程中，可能会因 OpenAPI 文档无效等严重问题而产生错误。系统会在不成功响应中将错误作为异常（如 `BadRequestException`）返回。出现错误时，新的 API 定义会被丢弃，现有 API 不会发生更改。

## 导入过程中出现警告
<a name="api-gateway-import-api-warnings"></a>

 在导入过程中，可能会因缺失模型引用等轻微问题而产生警告。出现警告时，如果请求 URL 中附加了 `failonwarnings=false` 查询表达式，则操作将会继续。否则更新就会回滚。默认情况下，将 `failonwarnings` 设置为 `false`。在这种情况下，系统会在生成的 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源中以字段形式返回警告。否则，系统会将警告作为异常中的一条消息返回。

# 从 API Gateway 导出 REST API
<a name="api-gateway-export-api"></a>

 使用 API Gateway 控制台或其他方式在 API Gateway 中创建和配置 REST API 后，您可以使用 API Gateway 导出 API（该 API 是 Amazon API Gateway 控制服务的一部分）将其导出到 OpenAPI 文件。要使用 API Gateway 导出 API，您需要签署您的 API 请求。有关签署请求的更多信息，请参阅《IAM 用户指南》**中的[签署 AWS API 请求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)。您可以在导出的 OpenAPI 定义文件中包含 API Gateway 集成扩展以及 [Postman](https://www.postman.com) 扩展。

**注意**  
使用 AWS CLI 导出 API 时，请务必包含扩展参数，如以下示例所示，以确保包含 `x-amazon-apigateway-request-validator` 扩展：  

```
aws apigateway get-export --parameters extensions='apigateway' --rest-api-id abcdefg123 --stage-name dev --export-type swagger latestswagger2.json
```

 如果 API 的负载并非 `application/json` 类型，则您无法将其导出。如果尝试导出，您将收到一条错误响应，指出未找到 JSON 正文模型。

## 请求导出 REST API
<a name="api-gateway-export-api-request"></a>

 借助 Export API，您可以提交 GET 请求，将要导出的 REST 指定为 URL 路径的一部分，以此来导出现有 REST API。请求 URL 的格式如下：

------
#### [ OpenAPI 3.0 ]

```
 https://<host>/restapis/<restapi_id>/stages/<stage_name>/exports/oas30
```

------
#### [ OpenAPI 2.0 ]

```
 https://<host>/restapis/<restapi_id>/stages/<stage_name>/exports/swagger
```

------

 您可以附加 `extensions` 查询字符串，以指定是否要包含 API Gateway 扩展（含 `integration` 值）或 Postman 扩展（含 `postman` 值）。

 此外，您还可以将 `Accept` 标头设置为 `application/json` 或 `application/yaml`，以分别接收 JSON 格式或 YAML 格式的 API 定义输出。

 有关使用 API Gateway 导出 API 提交 GET 请求的更多信息，请参阅 [GetExport](https://docs.aws.amazon.com/apigateway/latest/api/API_GetExport.html)。

**注意**  
 如果您在 API 中定义模型，那么这些模型的内容类型必须为“application/json”，这样 API Gateway 才能将其导出。否则，API Gateway 会引发异常，并显示“仅找到适用于……的非 JSON 正文模型”的错误消息。  
 模型必须包含属性或者被定义为特定 JSONSchema 类型。

## 下载 JSON 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-json"></a>

要下载 JSON 格式的 REST API OpenAPI 定义，请执行以下操作：

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------

 这里的 `<region>` 可以是 (比如说) `us-east-1`。有关提供 API Gateway 的所有区域，请参阅 [Regions and Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#apigateway_region)。

## 下载 YAML 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-yaml"></a>

要下载 YAML 格式的 REST API OpenAPI 定义，请执行以下操作：

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------

## 借助 Postman 扩展下载 JSON 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-json-with-postman"></a>

借助 Postman 导出并下载 JSON 格式的 REST API OpenAPI 定义，请执行以下操作：

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30?extensions=postman
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger?extensions=postman
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------

## 借助 API Gateway 集成下载 YAML 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-yaml-with-apig"></a>

要借助 API Gateway 集成导出并下载 YAML 格式的 REST API OpenAPI 定义，请执行以下操作：

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30?extensions=integrations
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger?extensions=integrations
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------

## 使用 API Gateway 控制台导出 REST API
<a name="api-gateway-export-api-from-console"></a>

[将 REST API 部署到一个阶段](set-up-deployments.md#create-deployment)之后，您可以使用 API Gateway 控制台将此阶段中的 API 导出到 OpenAPI 文件。

 在 API Gateway 控制台的**阶段**窗格中，选择**阶段操作**，然后选择**导出**。

![\[使用 API Gateway 控制台导出 REST API\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/export-new-console.png)


指定 **API 规范类型**、**格式**和**扩展**以下载您 API 的 OpenAPI 定义。