

# API Gateway HTTP API
<a name="http-api"></a>

REST API 和 HTTP API 都是 RESTful API 产品。REST API 支持的功能比 HTTP API 多，而 HTTP API 在设计时功能就极少，因此能够以更低的价格提供。有关更多信息，请参阅 [在 REST API 和 HTTP API 之间进行选择](http-api-vs-rest.md)。

您可以使用 HTTP API 将请求发送到 AWS Lambda 函数或任何可路由的 HTTP 终端节点。例如，您可以创建一个与后端上的 Lambda 函数集成的 HTTP API。当客户端调用您的 API 时，API Gateway 将请求发送到 Lambda 函数并将该函数的响应返回给客户端。

HTTP API 支持 [OpenID Connect](https://openid.net/developers/how-connect-works/) 和 [OAuth 2.0](https://oauth.net/2/) 授权。它们内置了对跨域资源共享 (CORS) 和自动部署的支持。

您可以使用AWS管理控制台、AWS CLI、API、CloudFormation 或开发工具包创建 HTTP API。

**Topics**
+ [开发 API Gateway 中的 HTTP API](http-api-develop.md)
+ [发布 HTTP API 供客户调用](http-api-publish.md)
+ [保护 API Gateway 中的 HTTP API](http-api-protect.md)
+ [监控 API Gateway 中的 HTTP API](http-api-monitor.md)
+ [排查 API Gateway 中 HTTP API 的问题](http-api-troubleshooting.md)

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

本节提供有关开发 API Gateway API 时所需的 API Gateway 功能的详细信息。

在开发 API Gateway API 时，您可以决定 API 的许多特征。这些特征取决于 API 的使用案例。例如，您可能希望仅允许某些客户端调用您的 API，或者您可能希望它对所有人都可用。您可能需要 API 调用来执行 Lambda 函数、进行数据库查询或调用应用程序。

**Topics**
+ [创建 HTTP API](#http-api-examples)
+ [创建针对 API Gateway 中 HTTP API 的路由](http-api-develop-routes.md)
+ [API Gateway 中 HTTP API 的 IP 地址类型](http-api-ip-address-type.md)
+ [控制和管理对 API Gateway 中的 HTTP API 的访问](http-api-access-control.md)
+ [针对 API Gateway 中的 HTTP API 创建集成](http-api-develop-integrations.md)
+ [为 API Gateway 中的 HTTP API 配置 CORS](http-api-cors.md)
+ [针对 API Gateway 中的 HTTP API 转换 API 请求和响应](http-api-parameter-mapping.md)
+ [将 OpenAPI 定义用于 API Gateway 中的 HTTP API](http-api-open-api.md)

## 创建 HTTP API
<a name="http-api-examples"></a>

要创建功能 API，您必须至少有一个路由、集成、阶段和部署。

以下示例显示如何创建具有 AWS Lambda 或 HTTP 集成、路由和默认阶段（配置为自动部署更改）的 API。

本指南以您已熟悉 API Gateway 和 Lambda 为前提。如需更详细的指南，请参阅[开始使用 API Gateway](getting-started.md)。

**Topics**
+ [使用 创建 HTTP APIAWS 管理控制台](#apigateway-http-api-create.console)
+ [使用AWS CLI 创建 HTTP API](#http-api-examples.cli.quick-create)

### 使用 创建 HTTP APIAWS 管理控制台
<a name="apigateway-http-api-create.console"></a>

1. 打开 [API Gateway 控制台](https://console.aws.amazon.com/apigateway)。

1. 选择 **Create API (创建 API)**。

1. 在 **HTTP API** 下，选择 **Build (构建)**。

1. 选择 **Add integration (添加集成)**，然后选择一个 AWS Lambda 函数或输入 HTTP 端点。

1. 对于 **Name (名称)**，输入 API 的名称。

1. 选择 **Review and create**。

1. 选择**创建**。

现在，您的 API 已准备好，可进行调用。您可以通过在浏览器中输入其调用 URL 或使用 Crul 来测试您的 API。

```
curl https://api-id.execute-api.us-east-2.amazonaws.com
```

### 使用AWS CLI 创建 HTTP API
<a name="http-api-examples.cli.quick-create"></a>

您可以使用“快速创建”功能，创建具有 Lambda 或 HTTP 集成、默认“捕获全部”路由和默认阶段（配置为自动部署更改）的 API。以下 [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) 使用快速创建来创建与后端上的 Lambda 函数集成的 API。

**注意**  
要调用 Lambda 集成，API Gateway 必须具有所需的权限。您可以使用基于资源的策略或 IAM 角色，为 API Gateway 授予权限以调用 Lambda 函数。如需了解更多信息，请参阅 *AWS Lambda 开发人员指南*中的 [AWS Lambda 权限](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html)。

**Example**  

```
aws apigatewayv2 create-api --name my-api --protocol-type HTTP --target arn:aws:lambda:us-east-2:123456789012:function:function-name
```

现在，您的 API 已准备好，可进行调用。您可以通过在浏览器中输入其调用 URL 或使用 Crul 来测试您的 API。

```
curl https://api-id.execute-api.us-east-2.amazonaws.com
```

# 创建针对 API Gateway 中 HTTP API 的路由
<a name="http-api-develop-routes"></a>

将直接传入 API 请求路由到后端资源。路由包含两部分：HTTP 方法和资源路径，例如，`GET /pets`。您可以为路由定义特定的 HTTP 方法。或者，您可以使用 `ANY` 方法匹配尚未为资源定义的所有方法。您可以创建一个 `$default` 路由，用作与任何其他路由不匹配的请求的“捕获全部”方法。

**注意**  
API Gateway 在将 URL 编码的请求参数传递给后端集成之前对其进行解码。

## 使用路径变量
<a name="http-api-routes-path-variables"></a>

您可以在 HTTP API 路由中使用路径变量。

例如，`GET /pets/{petID}` 路由捕获客户端提交给 `GET` 的 `https://api-id.execute-api.us-east-2.amazonaws.com/pets/6` 请求。

*贪婪的路径变量* 捕获路由的所有子资源。要创建“贪婪”路径变量，请将 `+` 添加到变量名称，例如 `{proxy+}`。“贪婪”路径变量必须位于资源路径的末尾。

## 使用查询字符串参数
<a name="http-api-routes-query-string-parameters"></a>

默认情况下，如果查询字符串参数包含在对 HTTP API 的请求中，则 API Gateway 会将查询字符串参数发送到您的后端集成。

例如，当客户端向 `https://api-id.execute-api.us-east-2.amazonaws.com/pets?id=4&type=dog` 发送请求时，查询字符串参数 `?id=4&type=dog` 将发送到您的集成。

## 使用 `$default` 路由
<a name="http-api-develop-routes.default"></a>

`$default` 路由捕获与 API 中的其他路由未显式匹配的请求。

当 `$default` 路由收到请求时，API Gateway 将完整的请求路径发送到集成。例如，您可以创建仅包含 `$default` 路由的 API，并将其与 `ANY` HTTP 终端节点集成到 `https://petstore-demo-endpoint.execute-api.com` 方法上。当您向 `https://api-id.execute-api.us-east-2.amazonaws.com/store/checkout` 发送请求时，API Gateway 会向 `https://petstore-demo-endpoint.execute-api.com/store/checkout` 发送请求。

要了解有关 HTTP 集成的更多信息，请参阅 [为 HTTP API 创建 HTTP 代理集成](http-api-develop-integrations-http.md)。

## 路由 API 请求
<a name="http-api-develop-routes.evaluation"></a>

当客户端发送 API 请求时，API Gateway 首先确定要将请求路由到哪个[阶段](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-stages.html) 。如果请求显式匹配某个阶段，则 API Gateway 将请求发送到该阶段。如果没有阶段与请求完全匹配，API Gateway 将请求发送到 `$default` 阶段。如果没有 `$default` 阶段，则 API 返回 `{"message":"Not Found"}` 并且不生成 CloudWatch 日志。

选择阶段后，API Gateway 将选择路由。API Gateway 使用以下优先级选择具有最佳匹配项的路由：

1. 路由和方法的完全匹配。

1. 匹配具有贪婪路径变量 (`{proxy+}`) 的路由和方法。

1. `$default` 路由。

如果没有与请求匹配的路由，API Gateway 将 `{"message":"Not Found"}` 返回到客户端。

例如，考虑一个具有 `$default` 阶段和以下示例路由的 API：

1. `GET /pets/dog/1`

1. `GET /pets/dog/{id}`

1. `GET /pets/{proxy+}`

1. `ANY /{proxy+}`

1. `$default`

   下表汇总了 API Gateway 如何将请求路由到示例路由。


| 请求 | 选定的路由 | 说明 | 
| --- | --- | --- | 
|  `GET https://api-id.execute-api.region.amazonaws.com/pets/dog/1`  |  `GET /pets/dog/1`  |  请求与此静态路由完全匹配。  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/pets/dog/2`  |  `GET /pets/dog/{id}`  |  请求与此路由完全匹配。  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/pets/cat/1`  |  `GET /pets/{proxy+}`  |  请求与路由不完全匹配。具有 `GET` 方法和贪婪路径变量的路由捕获此请求。  | 
| `POST https://api-id.execute-api.region.amazonaws.com/test/5` | `ANY /{proxy+}` |  `ANY` 方法匹配尚未为路由定义的所有方法。具有贪婪路径变量的路由比 `$default` 路由的优先级更高。  | 

# API Gateway 中 HTTP API 的 IP 地址类型
<a name="http-api-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)。

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

以下注意事项可能会影响您对 IP 地址类型的使用：
+ HTTP API 的默认 IP 地址类型是 IPv4。
+ 如果您将现有 API 的 IP 地址类型从 IPv4 更改为双堆栈，请确认任何控制 API 访问权限的策略均已更新以考虑 IPv6 调用。更改 IP 地址类型后，更改将立即生效。
+ 您的 API 可以映射到与 API 具有不同 IP 地址类型的自定义域名。如果您禁用默认 API 端点，则这可能会影响调用方调用 API 的方式。

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

您可以通过更新 API 的配置来更改 IP 地址类型。您可以使用 AWS 管理控制台、AWS CLI、CloudFormation 或 AWS SDK 更新 API 的配置。如果您更改 API 的 IP 地址类型，您不需要重新部署 API 即可使更改生效。

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

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

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

1. 选择 HTTP API。

1. 对于 **API 设置**，选择**编辑**。

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

1. 选择**保存**。

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

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

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

```
aws apigatewayv2 update-api \
    --api-id abcd1234 \
    --ip-address-type dualstack
```

输出将与以下内容类似：

```
{
    "ApiEndpoint": "https://abcd1234.execute-api.us-east-1.amazonaws.com",
    "ApiId": "abcd1234",
    "ApiKeySelectionExpression": "$request.header.x-api-key",
    "CreatedDate": "2025-02-04T22:20:20+00:00",
    "DisableExecuteApiEndpoint": false,
    "Name": "My-HTTP-API",
    "ProtocolType": "HTTP",
    "RouteSelectionExpression": "$request.method $request.path",
    "Tags": {},
    "NotificationUris": [],
    "IpAddressType": "dualstack"
}
```

------

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

API Gateway 支持多种用于控制和管理对 HTTP API 的访问的机制：
+ **Lambda 授权方** 使用 Lambda 函数来控制对 API 的访问。有关更多信息，请参阅 [使用 AWS Lambda 授权方控制对 HTTP API 的访问](http-api-lambda-authorizer.md)。
+ **JWT 授权方** 使用 JSON Web 令牌来控制对 API 的访问。有关更多信息，请参阅 [在 API Gateway 中使用 JWT 授权方控制对 HTTP API 的访问](http-api-jwt-authorizer.md)。
+ **标准AWS IAM 角色和策略**提供灵活且稳健的访问控制。您可以使用 IAM 角色和策略来控制哪些人可以创建和管理您的 API，以及谁可以调用它们。有关更多信息，请参阅 [在 API Gateway 中使用 IAM 授权来控制对 HTTP API 的访问](http-api-access-control-iam.md)。

为了改善您的安全状况，我们建议您为 HTTP API 上的所有路由配置授权方。为遵守各种合规性框架，您可能需要执行此操作。有关更多信息，请参阅《AWS Security Hub User Guide》**中的 [Amazon API Gateway Controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html)。

# 使用 AWS Lambda 授权方控制对 HTTP API 的访问
<a name="http-api-lambda-authorizer"></a>

您可以使用 Lambda 授权方以通过 Lambda 函数控制对 HTTP API 的访问。然后，当客户端调用您的 API 时，API Gateway 会调用您的 Lambda 函数。API Gateway 使用来自 Lambda 函数的响应来确定客户端是否可以访问您的 API。

## 负载格式版本
<a name="http-api-lambda-authorizer.payload-format"></a>

授权方负载格式版本指定 API Gateway 发送到 Lambda 授权方的数据格式，以及 API Gateway 如何解释来自 Lambda 的响应。如果未指定负载格式版本，则默认情况下 AWS 管理控制台 使用最新版本。如果您通过使用 AWS CLI、CloudFormation 或开发工具包创建 Lambda 授权方，则必须指定 `authorizerPayloadFormatVersion`。支持的值是 `1.0` 和 `2.0`。

 如果您需要与 REST API 兼容，请使用版本 `1.0`。

以下示例显示了每个负载格式版本的结构。

------
#### [ 2.0 ]

```
{
  "version": "2.0",
  "type": "REQUEST",
  "routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": ["user1", "123"],
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": ["cookie1", "cookie2"],
  "headers": {
    "header1": "value1",
    "header2": "value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "IP",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "pathParameters": { "parameter1": "value1" },
  "stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" }
}
```

------
#### [ 1.0 ]

```
{
  "version": "1.0",
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": "user1,123",
  "authorizationToken": "user1,123",
  "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"
  }
}
```

------

## Lambda 授权方响应格式
<a name="http-api-lambda-authorizer.payload-format-response"></a>

负载格式版本还确定您必须从 Lambda 函数返回的响应的结构。

### 格式 1.0 的 Lambda 函数响应
<a name="http-api-lambda-authorizer.v1"></a>

如果您选择 `1.0` 格式版本， Lambda 授权方必须返回允许或拒绝访问您的 API 路由的 IAM 策略。您可以在策略中使用标准 IAM 语法。有关 IAM 策略的示例，请参阅 [针对调用 API 的访问控制](api-gateway-control-access-using-iam-policies-to-invoke-api.md)。您可以使用 `$context.authorizer.property` 将上下文属性传递到 Lambda 集成或访问日志。`context` 对象是可选的，`claims` 是保留的占位符，不能用作上下文对象。要了解更多信息，请参阅“[自定义 HTTP API 访问日志](http-api-logging-variables.md)”。

**Example**    
****  

```
{
  "principalId": "abcdef", 
  "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": {
    "exampleKey": "exampleValue"
  }
}
```

### 格式 2.0 的 Lambda 函数响应
<a name="http-api-lambda-authorizer.v2"></a>

如果选择 `2.0` 格式版本，则可以从 Lambda 函数中返回使用标准 IAM 策略语法的布尔值或 IAM 策略。要返回布尔值，请为授权方启用简单响应。以下示例演示您必须对 Lambda 函数进行编码才能返回的格式。`context` 对象是可选的。您可以使用 `$context.authorizer.property` 将上下文属性传递到 Lambda 集成或访问日志。要了解更多信息，请参阅“[自定义 HTTP API 访问日志](http-api-logging-variables.md)”。

------
#### [ Simple response ]

```
{
  "isAuthorized": true/false,
  "context": {
    "exampleKey": "exampleValue"
  }
}
```

------
#### [ IAM policy ]

****  

```
{
  "principalId": "abcdef", 
  "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": {
    "exampleKey": "exampleValue"
  }
}
```

------

## Lambda 授权方函数示例
<a name="http-api-lambda-authorizer.example-code"></a>

以下示例 Node.js Lambda 函数演示您需要从 `2.0` 负载格式版本的 Lambda 函数返回的所需响应格式。

------
#### [ Simple response - Node.js ]

```
export const handler = async(event) => {
    let response = {
        "isAuthorized": false,
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": true,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    };
    
    if (event.headers.authorization === "secretToken") {
        console.log("allowed");
        response = {
            "isAuthorized": true,
            "context": {
                "stringKey": "value",
                "numberKey": 1,
                "booleanKey": true,
                "arrayKey": ["value1", "value2"],
                "mapKey": {"value1": "value2"}
            }
        };
    }

    return response;

};
```

------
#### [ Simple response - Python ]

```
import json


def lambda_handler(event, context):
    response = {
        "isAuthorized": False,
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": True,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    }

    try:
        if (event["headers"]["authorization"] == "secretToken"):
            response = {
                "isAuthorized": True,
                "context": {
                    "stringKey": "value",
                    "numberKey": 1,
                    "booleanKey": True,
                    "arrayKey": ["value1", "value2"],
                    "mapKey": {"value1": "value2"}
                }
            }
            print('allowed')
            return response
        else:
            print('denied')
            return response
    except BaseException:
        print('denied')
        return response
```

------
#### [ IAM policy - Node.js ]

```
export const handler = async(event) => {
  if (event.headers.authorization == "secretToken") {
    console.log("allowed");
    return {
      "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
      "policyDocument": {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
          "Action": "execute-api:Invoke",
          "Effect": "Allow",
          "Resource": event.routeArn
        }]
      },
      "context": {
        "stringKey": "value",
        "numberKey": 1,
        "booleanKey": true,
        "arrayKey": ["value1", "value2"],
        "mapKey": { "value1": "value2" }
      }
    };
  }
  else {
    console.log("denied");
    return {
      "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
      "policyDocument": {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
          "Action": "execute-api:Invoke",
          "Effect": "Deny",
          "Resource": event.routeArn
        }]
      },
      "context": {
        "stringKey": "value",
        "numberKey": 1,
        "booleanKey": true,
        "arrayKey": ["value1", "value2"],
        "mapKey": { "value1": "value2" }
      }
    };
  }
};
```

------
#### [ IAM policy - Python ]

```
import json


def lambda_handler(event, context):
    response = {
        # The principal user identification associated with the token sent by
        # the client.
        "principalId": "abcdef",
        "policyDocument": {
            "Version": "2012-10-17",		 	 	 
            "Statement": [{
                "Action": "execute-api:Invoke",
                "Effect": "Deny",
                "Resource": event["routeArn"]
            }]
        },
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": True,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    }

    try:
        if (event["headers"]["authorization"] == "secretToken"):
            response = {
                # The principal user identification associated with the token
                # sent by the client.
                "principalId": "abcdef",
                "policyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [{
                        "Action": "execute-api:Invoke",
                        "Effect": "Allow",
                        "Resource": event["routeArn"]
                    }]
                },
                "context": {
                    "stringKey": "value",
                    "numberKey": 1,
                    "booleanKey": True,
                    "arrayKey": ["value1", "value2"],
                    "mapKey": {"value1": "value2"}
                }
            }
            print('allowed')
            return response
        else:
            print('denied')
            return response
    except BaseException:
        print('denied')
        return response
```

------

## 身份来源
<a name="http-api-lambda-authorizer.identity-sources"></a>

您可以选择指定 Lambda 授权方的身份来源。身份来源指定对请求进行授权所需的数据的位置。例如，您可以将标头或查询字符串值指定为身份来源。如果您指定身份来源，则客户端必须将其包含在请求中。如果客户端的请求不包括身份源，则 API Gateway 不会调用您的 Lambda 授权方，客户端会收到 `401` 错误。

下表描述了 Lambda 授权方支持的身份源。


| **Type** | **示例** | **备注**： | 
| --- | --- | --- | 
| 标头值 | \$1request.header.name | 标头名称不区分大小写。 | 
| 查询字符串值 | \$1request.querystring.name | 查询字符串名称区分大小写。 | 
| 上下文变量 | \$1context.variableName | 受支持的[上下文变量](http-api-logging-variables.md)的值。 | 
| 阶段变量 | \$1stageVariables.variableName | [阶段变量](http-api-stages.stage-variables.md)的值。 | 

也可以直接从 Lambda 函数返回 ` {"errorMessage" : "Unauthorized"}`，来向您的客户端返回 `401` 错误。如果您直接从 Lambda 函数向客户端返回 `401` 错误，则在创建 Lambda 授权方时不要指定任何身份来源。

## 缓存授权方响应
<a name="http-api-lambda-authorizer.caching"></a>

您可以通过指定 [authorizerResultTtlInSeconds](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers.html#apis-apiid-authorizers-prop-createauthorizerinput-authorizerresultttlinseconds) 为 Lambda 授权方启用缓存。为授权方启用缓存时，API Gateway 使用授权方的身份来源作为缓存密钥。如果客户端在配置的 TTL 内在身份来源中指定了相同的参数，则 API Gateway 使用缓存的授权方结果，而不调用 Lambda 函数。

要启用缓存，授权方必须至少有一个身份来源。

如果为授权方启用简单响应，则授权方的响应将完全允许或拒绝与缓存的身份来源值匹配的所有 API 请求。要获得更精细的权限，请禁用简单响应并返回 IAM 策略。根据授权方，IAM 策略可能需要控制对多个身份来源的访问权限。

默认情况下，API Gateway 对使用授权方的 API 的所有路由使用缓存的授权方响应。要缓存每条路由的响应，请将 `$context.routeKey` 添加到授权方的身份来源中。

## 创建 Lambda 授权方
<a name="http-api-lambda-authorizer.example-create"></a>

创建 Lambda 授权方时，需要指定供 API Gateway 使用的 Lambda 函数。您必须使用函数的资源策略或 IAM 角色向 API Gateway 授予调用 Lambda 函数的权限。以下 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) 命令创建 Lambda 授权方：

```
aws apigatewayv2 create-authorizer \
    --api-id abcdef123 \
    --authorizer-type REQUEST \
    --identity-source '$request.header.Authorization' \
    --name lambda-authorizer \ 
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:my-function/invocations' \
    --authorizer-payload-format-version '2.0' \
    --enable-simple-responses
```

以下 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令更新 Lambda 函数的资源策略，来授予 API Gateway 调用函数的权限。如果 API Gateway 没有调用函数的权限，客户端会收到 `500 Internal Server Error`。

```
aws lambda add-permission \
    --function-name my-authorizer-function \
    --statement-id apigateway-invoke-permissions-abc123 \ 
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/authorizers/authorizer-id"
```

创建授权方并授予 API Gateway 调用授权方的权限后，请更新您的路由以使用此授权方。以下 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 命令将 Lambda 授权方添加到路由中。如果 Lambda 授权方使用策略缓存，请务必更新策略以控制其它路由的访问权限。

```
aws apigatewayv2 update-route \
    --api-id abcdef123 \
    --route-id abc123 \
    --authorization-type CUSTOM \
    --authorizer-id def123
```

## Lambda 授权方故障排除
<a name="http-api-lambda-authorizer.troubleshooting"></a>

如果 API Gateway 无法调用 Lambda 授权方，或者您的 Lambda 授权方返回无效格式的响应，则客户端将收到 `500 Internal Server Error`。

要排除错误，请为 API 阶段[启用访问日志记录](http-api-logging.md)。以 `$context.authorizer.error` 日志格式包含日志记录变量。

如果日志表明 API Gateway 无权调用您的函数，请更新函数的资源策略或提供 IAM 角色，以授予 API Gateway 调用授权方的权限。

如果日志表明您的 Lambda 函数返回无效响应，请验证您的 Lambda 函数以[所需格式](#http-api-lambda-authorizer.payload-format-response)返回响应。

# 在 API Gateway 中使用 JWT 授权方控制对 HTTP API 的访问
<a name="http-api-jwt-authorizer"></a>

您可以使用 JSON Web 令牌 (JWT) 作为 [OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html) 和 [OAuth 2.0](https://oauth.net/2/) 框架的一部分来限制客户端对您的 API 的访问。

如果您为 API 的路由配置 JWT 授权方，API Gateway 将验证客户端通过 API 请求提交的 JWT。API Gateway 根据令牌中的令牌验证和（可选）作用域来允许或拒绝请求。如果为路由配置作用域，则令牌必须至少包含路由的作用域之一。

您可以为 API 的每个路由配置不同的授权方，也可以为多个路由使用同一个授权方。

**注意**  
没有标准的机制可以将 JWT 访问令牌与其他类型的 JWT（如 OpenID Connect ID 令牌）区分开来。除非您需要 ID 令牌进行 API 授权，否则我们建议您将路由配置为需要授权范围。您还可以将 JWT 授权方配置为需要相应的发布者或受众（身份提供商仅在发布 JWT 访问令牌时才使用他们）。

## 使用 JWT 授权方授权 API 请求
<a name="http-api-jwt-authorizer.evaluation"></a>

API Gateway 使用以下常规工作流程向配置为使用 JWT 授权方的路由授权请求。

1. 检查 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource) 是否有令牌。`identitySource` 只能包含令牌或前缀为 `Bearer` 的令牌。

1. 对令牌解码。

1. 使用从发布者的 `jwks_uri` 中提取的公有密钥检查令牌的算法和签名。目前仅支持基于 RSA 的算法。API Gateway 可以将公有密钥缓存两个小时。最佳实践是，在轮换密钥时，留出一段宽限期，在此期间旧密钥和新密钥均有效。

1. 验证声明。API Gateway 评估以下令牌声明：
   +  [https://datatracker.ietf.org/doc/html/rfc7517#section-4.5](https://datatracker.ietf.org/doc/html/rfc7517#section-4.5) – 令牌必须具有与签署令牌的 `jwks_uri` 中的键匹配的标头声明。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1) – 必须匹配为授权方配置的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration)。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3) 或 `client_id` – 必须匹配为授权方配置的其中一个 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration) 条目。API Gateway 只有在 `aud` 不存在时才验证 `client_id`。当 `aud` 和 `client_id` 同时存在时，API Gateway 会评估 `aud`。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) – 必须在 UTC 中的当前时间之后。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5) – 必须在 UTC 中的当前时间之前。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6) – 必须在 UTC 中的当前时间之前。
   + [https://datatracker.ietf.org/doc/html/rfc6749#section-3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) 或 `scp` – 令牌必须至少包含路由的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes) 中的一个作用域。

如果这些步骤中的任何一个步骤失败，API Gateway 都会拒绝 API 请求。

验证 JWT 后，API Gateway 将令牌中的声明传递给 API 路由的集成。后端资源（如 Lambda 函数）可以访问 JWT 声明。例如，如果 JWT 包含了身份声明 `emailID`，则它在 `$event.requestContext.authorizer.jwt.claims.emailID` 中可供 Lambda 集成使用。有关 API Gateway 向 Lambda 集成发送的负载的更多信息，请参阅[针对 API Gateway 中的 HTTP API 创建 AWS Lambda 代理集成](http-api-develop-integrations-lambda.md)。

## 创建 JWT 授权方
<a name="http-api-jwt-authorizer.create"></a>

在创建 JWT 授权方之前，必须向身份提供商注册客户端应用程序。您必须还创建了 HTTP API。有关创建 HTTP API 的示例，请参阅 [创建 HTTP API](http-api-develop.md#http-api-examples)。

### 使用控制台创建 JWT 授权方
<a name="http-api-jwt-authorizer.create.console"></a>

以下步骤说明如何使用控制台创建 JWT 授权方。

**使用控制台创建 JWT 授权方**

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

1. 选择 HTTP API。

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

1. 选择**管理授权方**选项卡。

1. 选择**创建**。

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

1. 配置您的 JWT 授权方，并指定用于定义令牌来源的**身份来源**。

1. 选择**创建**。

#### 使用 AWS CLI 创建 JWT 授权方
<a name="http-api-jwt-authorizer.create.cli"></a>

以下 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) 命令创建 JWT 授权方。对于 `jwt-configuration`，为您的身份提供商指定 `Audience` 和 `Issuer`。如果您使用 Amazon Cognito 作为身份提供者，则 `IssuerUrl` 为 `https://cognito-idp.us-east-2.amazonaws.com/userPoolID`。

```
aws apigatewayv2 create-authorizer \
    --name authorizer-name \
    --api-id api-id \
    --authorizer-type JWT \
    --identity-source '$request.header.Authorization' \
    --jwt-configuration Audience=audience,Issuer=IssuerUrl
```

##### 使用 AWS CloudFormation 创建 JWT 授权方
<a name="http-api-jwt-cfn.create"></a>

以下 CloudFormation 模板通过将 Amazon Cognito 用作身份提供者的 JWT 授权方创建 HTTP API。

CloudFormation 模板的输出是 Amazon Cognito 托管用户界面的 URL，客户可以在其中注册并登录来接收 JWT。客户端登录后，会使用 URL 中的访问令牌将客户端重定向到您的 HTTP API。要使用访问令牌调用 API，请将 URL 中的 `#` 更改为 `?`，来使用该令牌作为查询字符串参数。

##### 示例 CloudFormation 模板
<a name="http-api-jwt-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Example HTTP API with a JWT authorizer. This template includes an Amazon Cognito user pool as the issuer for the JWT authorizer 
  and an Amazon Cognito app client as the audience for the authorizer. The outputs include a URL for an Amazon Cognito hosted UI where clients can 
  sign up and sign in to receive a JWT. After a client signs in, the client is redirected to your HTTP API with an access token 
  in the URL. To invoke the API with the access token, change the '#' in the URL to a '?' to use the token as a query string parameter.

Resources:
  MyAPI:
    Type: AWS::ApiGatewayV2::Api
    Properties: 
      Description: Example HTTP API
      Name: api-with-auth
      ProtocolType: HTTP
      Target: !GetAtt MyLambdaFunction.Arn
  DefaultRouteOverrides:
    Type: AWS::ApiGatewayV2::ApiGatewayManagedOverrides
    Properties: 
      ApiId: !Ref MyAPI
      Route: 
        AuthorizationType: JWT
        AuthorizerId: !Ref JWTAuthorizer
  JWTAuthorizer:
    Type: AWS::ApiGatewayV2::Authorizer
    Properties: 
      ApiId: !Ref MyAPI
      AuthorizerType: JWT
      IdentitySource: 
        - '$request.querystring.access_token'
      JwtConfiguration: 
        Audience: 
        - !Ref AppClient
        Issuer: !Sub https://cognito-idp.${AWS::Region}.amazonaws.com/${UserPool}
      Name: test-jwt-authorizer
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs18.x
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              const response = {
                  statusCode: 200,
                  body: JSON.stringify('Hello from the ' + event.routeKey + ' route!'),
              };
              return response;
          };
  APIInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MyAPI}/$default/$default
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17		 	 	 '
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: http-api-user-pool
      AutoVerifiedAttributes:
        - email
      Schema:
        - Name: name
          AttributeDataType: String
          Mutable: true
          Required: true
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
  AppClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      AllowedOAuthFlows: 
        - implicit
      AllowedOAuthScopes: 
        - aws.cognito.signin.user.admin
        - email
        - openid
        - profile
      AllowedOAuthFlowsUserPoolClient: true
      ClientName: api-app-client
      CallbackURLs:
        - !Sub https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      UserPoolId: !Ref UserPool
      SupportedIdentityProviders:
        - COGNITO 
  HostedUI:
    Type: AWS::Cognito::UserPoolDomain
    Properties: 
      Domain: !Join
        - '-'
        - - !Ref MyAPI
          - !Ref AppClient
      UserPoolId: !Ref UserPool
Outputs:
  SignupURL:
    Value: !Sub https://${HostedUI}.auth.${AWS::Region}.amazoncognito.com/login?client_id=${AppClient}&response_type=token&scope=email+profile&redirect_uri=https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
```

## 更新路由来使用 JWT 授权方
<a name="http-api-jwt-authorizer.create.route"></a>

您可以使用控制台、AWS CLI 或 AWS SDK 更新路由来使用 JWT 授权方。

### 使用控制台更新路由来使用 JWT 授权方
<a name="http-api-jwt-authorizer.create.route"></a>

以下步骤说明如何使用控制台更新路由来使用 JWT 授权方。

**使用控制台创建 JWT 授权方**

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

1. 选择 HTTP API。

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

1. 选择一个方法，然后从下拉菜单中选择您的授权方，然后选择**附加授权方**。

#### 使用 AWS CLI 更新路由来使用 JWT 授权方
<a name="http-api-jwt-authorizer.create.route"></a>

以下 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 命令更新路由以使用 JWT 授权方：

```
aws apigatewayv2 update-route \
   --api-id api-id  \
   --route-id route-id  \
   --authorization-type JWT \
   --authorizer-id authorizer-id \
   --authorization-scopes user.email
```

# 在 API Gateway 中使用 IAM 授权来控制对 HTTP API 的访问
<a name="http-api-access-control-iam"></a>

您可以为 HTTP API 路由启用 IAM 授权。启用 IAM 授权后，客户端必须使用[签名版本 4（SigV4）](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html)，才能使用 AWS 凭证签署其请求。仅当客户端对路由具有 `execute-api` 权限时，API Gateway 才会调用您的 API 路由。

用于 HTTP API 的 IAM 授权类似于用于 [REST API](api-gateway-control-access-using-iam-policies-to-invoke-api.md) 的授权。

**注意**  
HTTP API 目前不支持资源策略。

有关授予客户端调用 API 的 IAM 权限的策略示例，请参阅 [针对调用 API 的访问控制](api-gateway-control-access-using-iam-policies-to-invoke-api.md)。

## 为路由启用 IAM 授权
<a name="http-api-access-control-iam-example"></a>

以下 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 命令为 HTTP API 路由启用 IAM 授权:

```
aws apigatewayv2 update-route \
    --api-id abc123 \
    --route-id abcdef \
    --authorization-type AWS_IAM
```

# 针对 API Gateway 中的 HTTP API 创建集成
<a name="http-api-develop-integrations"></a>

*集成* 将路由连接到后端资源。HTTP API 支持 Lambda 代理、AWS服务和 HTTP 代理集成。例如，您可以配置对 API 的 `POST` 路由的 `/signup` 请求，以便与处理注册客户的 Lambda 函数集成。

**Topics**
+ [针对 API Gateway 中的 HTTP API 创建 AWS Lambda 代理集成](http-api-develop-integrations-lambda.md)
+ [为 HTTP API 创建 HTTP 代理集成](http-api-develop-integrations-http.md)
+ [针对 API Gateway 中的 HTTP API 创建 AWS 服务集成](http-api-develop-integrations-aws-services.md)
+ [针对 API Gateway 中的 HTTP API 创建私有集成](http-api-develop-integrations-private.md)

# 针对 API Gateway 中的 HTTP API 创建 AWS Lambda 代理集成
<a name="http-api-develop-integrations-lambda"></a>

通过 Lambda 代理集成，您可以将 API 路由与 Lambda 函数集成。当客户端调用您的 API 时，API Gateway 将请求发送到 Lambda 函数并将该函数的响应返回给客户端。有关创建 HTTP API 的示例，请参阅 [创建 HTTP API](http-api-develop.md#http-api-examples)。

## 负载格式版本
<a name="http-api-develop-integrations-lambda.proxy-format"></a>

负载格式版本指定 API Gateway 发送到 Lambda 集成的事件的格式，以及 API Gateway 如何解释来自 Lambda 的响应。如果未指定负载格式版本，则默认情况下 AWS 管理控制台 使用最新版本。如果您通过使用 AWS CLI、CloudFormation 或开发工具包创建 Lambda 集成，则必须指定 `payloadFormatVersion`。支持的值是 `1.0` 和 `2.0`。

有关如何设置 `payloadFormatVersion` 的更多信息，请参阅 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html)。有关如何确定现有集成的 `payloadFormatVersion` 的更多信息，请参阅 [get-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-integration.html)。

### 负载格式差异
<a name="http-api-develop-integrations-lambda.proxy-format-differences"></a>

以下列表显示了 `1.0` 和 `2.0` 负载格式版本之间的差异：
+ 格式 `2.0` 没有 `multiValueHeaders` 或 `multiValueQueryStringParameters` 字段。重复的标头使用逗号组合，包含在 `headers` 字段中。重复的查询字符串使用逗号组合，包含在 `queryStringParameters` 字段中。
+ 格式 `2.0` 具有 `rawPath`。如果您使用 API 映射将阶段连接到自定义域名，`rawPath` 不会提供 API 映射值。使用格式 `1.0` 和 `path` 可访问自定义域名的 API 映射。
+ 格式 `2.0` 包含一个新 `cookies` 字段。请求中的所有 Cookie 标头均使用逗号组合并添加到 `cookies` 字段中。在对客户端的响应中，每个 Cookie 都成为一个 `set-cookie` 标头。

### 负载格式结构
<a name="http-api-develop-integrations-lambda.proxy-format-structure"></a>

以下示例显示了每个负载格式版本的结构。所有标头名称均为小写。

------
#### [ 2.0 ]

```
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "headers": {
    "header1": "value1",
    "header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "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"
        }
      }
    },
    "authorizer": {
      "jwt": {
        "claims": {
          "claim1": "value1",
          "claim2": "value2"
        },
        "scopes": [
          "scope1",
          "scope2"
        ]
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "192.0.2.1",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from Lambda",
  "pathParameters": {
    "parameter1": "value1"
  },
  "isBase64Encoded": false,
  "stageVariables": {
    "stageVariable1": "value1",
    "stageVariable2": "value2"
  }
}
```

------
#### [ 1.0 ]

```
{
  "version": "1.0",
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
    "header1": "value1",
    "header2": "value2"
  },
  "multiValueHeaders": {
    "header1": [
      "value1"
    ],
    "header2": [
      "value1",
      "value2"
    ]
  },
  "queryStringParameters": {
    "parameter1": "value1",
    "parameter2": "value"
  },
  "multiValueQueryStringParameters": {
    "parameter1": [
      "value1",
      "value2"
    ],
    "parameter2": [
      "value"
    ]
  },
  "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": "192.0.2.1",
      "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
}
```

------

## Lambda 函数响应格式
<a name="http-api-develop-integrations-lambda.response"></a>

负载格式版本确定 Lambda 函数必须返回的响应结构。

### 格式 1.0 的 Lambda 函数响应
<a name="http-api-develop-integrations-lambda.v1"></a>

对于 `1.0` 格式版本，Lambda 集成必须返回采用以下 JSON 格式的响应：

**Example**  

```
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headername": "headervalue", ... },
    "multiValueHeaders": { "headername": ["headervalue", "headervalue2", ...], ... },
    "body": "..."
}
```

### 格式 2.0 的 Lambda 函数响应
<a name="http-api-develop-integrations-lambda.v2"></a>

使用 `2.0` 格式版本，API Gateway 可以推断您的响应格式。如果您的 Lambda 函数返回有效的 JSON 并且没有返回 `statusCode`，API Gateway 会做出以下假设：
+ `isBase64Encoded` 为 `false`。
+ `statusCode` 为 `200`。
+ `content-type` 为 `application/json`。
+ `body` 是函数的响应。

以下示例显示 Lambda 函数的输出和 API Gateway 的解释。


| Lambda 函数输出 | API Gateway 解释 | 
| --- | --- | 
|  <pre>"Hello from Lambda!"</pre>  |  <pre>{<br />  "isBase64Encoded": false,<br />  "statusCode": 200,<br />  "body": "Hello from Lambda!",<br />  "headers": {<br />    "content-type": "application/json"<br />  }<br />}</pre>  | 
|  <pre>{ "message": "Hello from Lambda!" }</pre>  |  <pre>{<br />  "isBase64Encoded": false,<br />  "statusCode": 200,<br />  "body": "{ \"message\": \"Hello from Lambda!\" }",<br />  "headers": {<br />    "content-type": "application/json"<br />  }<br />}</pre>  | 

要自定义响应，您的 Lambda 函数应返回以下格式的响应。

```
{
    "cookies" : ["cookie1", "cookie2"],
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headername": "headervalue", ... },
    "body": "Hello from Lambda!"
}
```

# 为 HTTP API 创建 HTTP 代理集成
<a name="http-api-develop-integrations-http"></a>

通过 HTTP 代理集成，您可以将 API 路由连接到可公开路由的 HTTP 终端节点。使用这种集成类型，API Gateway 在前端和后端之间传递完整的请求和响应。

要创建 HTTP 代理集成，请提供可公开路由 HTTP 终端节点的 URL。

## 具有路径变量的 HTTP 代理集成
<a name="http-api-develop-integrations-http-proxy"></a>

您可以在 HTTP API 路由中使用路径变量。

例如，路由 `/pets/{petID}` 捕获对 `/pets/6` 的请求。您可以在集成 URI 中引用路径变量，以将变量的内容发送到集成。示例是 `/pets/extendedpath/{petID}`。

您可以使用“贪婪”路径变量来捕获路由的所有子资源。要创建“贪婪”路径变量，请将 `+` 添加到变量名称，例如 `{proxy+}`。

要设置具有捕获所有请求的 HTTP 代理集成的路由，请使用“贪婪”路径变量创建 API 路由（例如，`/parent/{proxy+}`）。将路由与 `https://petstore-demo-endpoint.execute-api.com/petstore/{proxy}` 方法上的 HTTP 终端节点（例如 `ANY`）集成。“贪婪”路径变量必须位于资源路径的末尾。

# 针对 API Gateway 中的 HTTP API 创建 AWS 服务集成
<a name="http-api-develop-integrations-aws-services"></a>

您可以使用*一流的集成*将 HTTP API 与AWS服务集成。一流的集成会将 HTTP API 路由连接到AWS服务 API。当客户端调用由一流集成支持的路由时，API Gateway 会为您调用AWS服务 API。例如，您可以使用一流的集成向 Amazon Simple Queue Service 队列发送消息，或启动 AWS Step Functions 状态机。有关支持的服务操作，请参阅 [集成子类型参考](http-api-develop-integrations-aws-services-reference.md)。

## 映射请求参数
<a name="http-api-develop-integrations-aws-services-parameter-mapping"></a>

一流的集成具有必需和可选的参数。必须配置所有必需的参数才能创建集成。您可以使用在运行时动态评估的静态值或映射参数。有关支持的集成和参数的完整列表，请参阅[集成子类型参考](http-api-develop-integrations-aws-services-reference.md)。

下表描述了支持的映射请求参数。


| 类型 | 示例 | 备注 | 
| --- | --- | --- | 
| 标头值 | \$1request.header.name | 标头名称不区分大小写。API Gateway 将多个标头值与逗号组合在一起，例如 "header1": "value1,value2"。 | 
| 查询字符串值 | \$1request.querystring.name | 查询字符串名称区分大小写。API Gateway 将多个值与逗号组合在一起，例如 "querystring1": "Value1,Value2"。 | 
| 路径参数 | \$1request.path.name | 请求中路径参数的值。例如，如果路由为 /pets/\$1petId\$1，则可以从具有 \$1request.path.petId 的请求中映射 petId 参数。 | 
| 请求正文传递 | \$1request.body | API Gateway 传递整个请求正文。 | 
| 请求正文 | \$1request.body.name | [JSON 路径表达式](https://goessner.net/articles/JsonPath/index.html#e2)。不支持递归下降 (\$1request.body..name) 和筛选表达式 (?(expression))。 当您指定 JSON 路径时，API Gateway 会在请求正文的 100 KB 处将其截断，然后应用选择表达式。要发送大于 100 KB 的负载，请指定 `$request.body`。  | 
| 上下文变量 | \$1context.variableName | 受支持的[上下文变量](http-api-logging-variables.md)的值。 | 
| 阶段变量 | \$1stageVariables.variableName | [阶段变量](http-api-stages.stage-variables.md)的值。 | 
| 静态值 | string | 常量值。 | 

## 创建一流的集成
<a name="http-api-develop-integrations-aws-services-example"></a>

在创建一流集成之前，您必须创建一个 IAM 角色，该角色向 API Gateway 授予调用您要集成的AWS服务操作的权限。如需了解详情，请参阅[为AWS服务创建角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html)。

要创建一流集成，请选择受支持的AWS服务操作（例如 `SQS-SendMessage`），配置请求参数，然后提供一个角色来授予 API Gateway 调用集成的AWS服务 API 的权限。根据集成子类型，需要不同的请求参数。要了解更多信息，请参阅 [集成子类型参考](http-api-develop-integrations-aws-services-reference.md)。

以下 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令创建发送 Amazon SQS 消息的集成。

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-subtype SQS-SendMessage \
    --integration-type AWS_PROXY \
    --payload-format-version 1.0 \
    --credentials-arn arn:aws:iam::123456789012:role/apigateway-sqs \
    --request-parameters '{"QueueUrl": "$request.header.queueUrl", "MessageBody": "$request.body.message"}'
```

## 使用 CloudFormation 创建一流的集成
<a name="http-api-develop-integrations-aws-services-example-cfn"></a>

以下示例显示了一个 CloudFormation 代码段，该代码段可创建一个与 Amazon EventBridge 进行一流集成的 `/{source}/{detailType}` 路径。

`Source` 参数映射到 `{source}` 路径参数，`DetailType` 映射到 `{DetailType}` 路径参数，`Detail`参数映射到请求正文。

该代码段不显示事件总线或授予 API Gateway 调用 `PutEvents` 操作的权限的 IAM 角色。

```
Route:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref HttpApi
      AuthorizationType: None
      RouteKey: 'POST /{source}/{detailType}'
      Target: !Join 
        - /
        - - integrations
          - !Ref Integration
  Integration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref HttpApi
      IntegrationType: AWS_PROXY
      IntegrationSubtype: EventBridge-PutEvents
      CredentialsArn: !GetAtt EventBridgeRole.Arn
      RequestParameters:
        Source: $request.path.source
        DetailType: $request.path.detailType
        Detail: $request.body
        EventBusName: !GetAtt EventBus.Arn
      PayloadFormatVersion: "1.0"
```

# 集成子类型参考
<a name="http-api-develop-integrations-aws-services-reference"></a>

HTTP API 支持以下[集成子类型](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationsubtype)。

**Topics**
+ [EventBridge-PutEvents 1.0](#EventBridge-PutEvents)
+ [SQS-SendMessage 1.0](#SQS-SendMessage)
+ [SQS-ReceiveMessage 1.0](#SQS-ReceiveMessage)
+ [SQS-DeleteMessage 1.0](#SQS-DeleteMessage)
+ [SQS-PurgeQueue 1.0](#SQS-PurgeQueue)
+ [AppConfig-GetConfiguration 1.0](#AppConfig-GetConfiguration)
+ [Kinesis-PutRecord 1.0](#Kinesis-PutRecord)
+ [StepFunctions-StartExecution 1.0](#StepFunctions-StartExecution)
+ [StepFunctions-StartSyncExecution 1.0](#StepFunctions-StartSyncExecution)
+ [StepFunctions-StopExecution 1.0](#StepFunctions-StopExecution)

## EventBridge-PutEvents 1.0
<a name="EventBridge-PutEvents"></a>

将自定义事件发送到 Amazon EventBridge，以便将其与规则进行匹配。


| 参数 | 必需 | 
| --- | --- | 
| Detail | True | 
| DetailType | True | 
| 源 | True | 
| Time | False | 
| EventBusName | False | 
| 资源 | False | 
| 区域 | False | 
| TraceHeader | False | 

要了解更多信息，请参阅 *Amazon EventBridge API 参考* 中的 [PuteVentts](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)。

## SQS-SendMessage 1.0
<a name="SQS-SendMessage"></a>

向指定的队列传送了一条消息。


| 参数 | 必需 | 
| --- | --- | 
| QueueUrl | True | 
| MessageBody | True | 
| DelaySeconds | False | 
| MessageAttributes | False | 
| MessageDeduplicationId | False | 
| MessageGroupId | False | 
| MessageSystemAttributes | False | 
| 区域 | False | 

要了解更多信息，请参阅 *Amazon Simple Queue Service API 参考* 中的 [SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)。

## SQS-ReceiveMessage 1.0
<a name="SQS-ReceiveMessage"></a>

从指定的队列中检索一条或多条消息（最多 10 条）。


| 参数 | 必需 | 
| --- | --- | 
| QueueUrl | True | 
| AttributeNames | False | 
| MaxNumberOfMessages | False | 
| MessageAttributeNames | False | 
| ReceiveRequestAttemptId | False | 
| VisibilityTimeout | False | 
| WaitTimeSeconds | False | 
| 区域 | False | 

要了解更多信息，请参阅 *Amazon Simple Queue Service API 参考* 中的 [ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)。

## SQS-DeleteMessage 1.0
<a name="SQS-DeleteMessage"></a>

从指定的队列中删除指定的消息。


| 参数 | 必需 | 
| --- | --- | 
| ReceiptHandle | True | 
| QueueUrl | True | 
| 区域 | False | 

要了解更多信息，请参阅 *Amazon Simple Queue Service API 参考* 中的 [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)。

## SQS-PurgeQueue 1.0
<a name="SQS-PurgeQueue"></a>

删除指定队列中的所有消息。


| 参数 | 必需 | 
| --- | --- | 
| QueueUrl | True | 
| 区域 | False | 

要了解更多信息，请参阅 *Amazon Simple Queue Service API 参考* 中的 [PurgeQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_PurgeQueue.html)。

## AppConfig-GetConfiguration 1.0
<a name="AppConfig-GetConfiguration"></a>

接收有关配置的信息。


| 参数 | 必需 | 
| --- | --- | 
| 应用程序 | True | 
| 环境 | True | 
| 配置 | True | 
| ClientId | True | 
| ClientConfigurationVersion | False | 
| 区域 | False | 

如需了解详情，请参阅*AWS AppConfig API 参考*中的 [GetConfiguration](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_GetConfiguration.html)。

## Kinesis-PutRecord 1.0
<a name="Kinesis-PutRecord"></a>

将单个数据记录写入 Amazon Kinesis 数据流。


| 参数 | 必需 | 
| --- | --- | 
| StreamName | True | 
| 数据 | True | 
| PartitionKey | True | 
| SequenceNumberForOrdering | False | 
| ExplicitHashKey | False | 
| 区域 | False | 

要了解更多信息，请参阅 *Amazon Kinesis Data Streams API 参考* 中的 [PutRecord](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html)。

## StepFunctions-StartExecution 1.0
<a name="StepFunctions-StartExecution"></a>

启动状态机的一次执行。


| 参数 | 必需 | 
| --- | --- | 
| StateMachineArn | True | 
| 名称 | False | 
| 输入 | False | 
| 区域 | False | 

如需了解详情，请参阅 *AWS Step Functions API 参考*中的 [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html)。

## StepFunctions-StartSyncExecution 1.0
<a name="StepFunctions-StartSyncExecution"></a>

启动同步状态机执行。


| 参数 | 必需 | 
| --- | --- | 
| StateMachineArn | True | 
| 名称 | False | 
| 输入 | False | 
| 区域 | False | 
| TraceHeader | False | 

如需了解详情，请参阅 *AWS Step Functions API 参考*中的 [StartSyncExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartSyncExecution.html)。

## StepFunctions-StopExecution 1.0
<a name="StepFunctions-StopExecution"></a>

停止一次执行。


| 参数 | 必需 | 
| --- | --- | 
| ExecutionArn | True | 
| 原因 | False | 
| 错误 | False | 
| 区域 | False | 

如需了解详情，请参阅 *AWS Step Functions API 参考*中的 [StopExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StopExecution.html)。

# 针对 API Gateway 中的 HTTP API 创建私有集成
<a name="http-api-develop-integrations-private"></a>

私有集成使您能够与 VPC 中的私有资源（如 Application Load Balancer 或基于 Amazon ECS 容器的应用程序）创建 API 集成。

您可以使用私有集成公开 VPC 中的资源，以便 VPC 外部的客户端访问。您可以使用 API Gateway 支持的任何[授权方法](http-api-access-control.md)来控制对 API 的访问。

**注意**  
要创建私有集成，您必须首先创建 VPC 链接。现在，HTTP 和 REST API 都支持 VPC 链接 V2。要了解有关 VPC 链接 V2 的更多信息，请参阅 [在 API Gateway 中设置 VPC 链接 V2](apigateway-vpc-links-v2.md)。

创建 VPC 链接 V2 后，您可以设置私有集成，以连接到应用程序负载均衡器、网络负载均衡器或注册到 AWS Cloud Map 服务的资源。

## 注意事项
<a name="http-api-develop-integrations-private-considerations"></a>

以下注意事项可能会影响您对私有集成的使用：
+ 所有资源必须由同一 AWS 账户拥有。这包括负载均衡器或 AWS Cloud Map 服务、VPC 链接和 HTTP API。
+ 默认情况下，私有集成流量使用 HTTP 协议。要使用 HTTPS，请指定一个 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html)。要使用 AWS 管理控制台执行此操作，请在创建私有集成时，选择**高级设置**，然后输入安全服务器名称。
+ 对于私有集成，API Gateway 在对后端资源的请求中包括 API 端点的[阶段](http-api-stages.md)部分。例如，对 API 的 `test` 阶段的请求在对私有集成的请求中包含 `test/route-path`。要从对后端资源的请求中删除阶段名，请使用[参数映射](http-api-parameter-mapping.md)覆盖 `$request.path` 的请求路径。

## 使用 Application Load Balancer 或 Network Load Balancer 创建私有集成
<a name="http-api-develop-integrations-private-ELB"></a>

在创建私有集成之前，您必须创建 VPC 链接 V2。要了解有关 VPC 链接 V2 的更多信息，请参阅 [在 API Gateway 中设置 VPC 链接 V2](apigateway-vpc-links-v2.md)。

要创建与 Application Load Balancer 或 Network Load Balancer 的私有集成，请创建 HTTP 代理集成，指定要使用的 VPC 链接，并提供负载均衡器的侦听器 ARN。

以下 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令创建私有集成，该集成通过 VPC 链接连接到负载均衡器。

```
aws apigatewayv2 create-integration --api-id api-id --integration-type HTTP_PROXY \
    --integration-method GET --connection-type VPC_LINK \
    --connection-id VPC-link-ID \
    --integration-uri arn:aws:elasticloadbalancing:us-east-2:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/0467ef3c8400ae65
    --payload-format-version 1.0
```

## 使用 AWS Cloud Map 服务发现创建私有集成
<a name="http-api-develop-integrations-private-Cloud-Map"></a>

在创建私有集成之前，您必须创建 VPC 链接 V2。要了解有关 VPC 链接的更多信息，请参阅 [在 API Gateway 中设置 VPC 链接 V2](apigateway-vpc-links-v2.md)。

为了与 AWS Cloud Map 集成，API Gateway 使用 `DiscoverInstances` 来识别资源。您可以使用查询参数来定位特定资源。已注册资源的属性必须包括 IP 地址和端口。API Gateway 在从 `DiscoverInstances` 返回的运行状况良好的资源之间分发请求。如需了解详情，请参阅 AWS Cloud Map API 参考中的 [DiscoverInstances](https://docs.aws.amazon.com/cloud-map/latest/api/API_DiscoverInstances.html)。

**注意**  
如果您使用 Amazon ECS 填充 AWS Cloud Map 中的条目，则必须将您的 Amazon ECS 任务配置为通过 Amazon ECS 服务发现使用 SRV 记录，或者开启 Amazon ECS Service Connect。有关更多信息，请参阅《Amazon Elastic Container Service 开发人员指南》中[互连服务](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/interconnecting-services.html)。

要使用 AWS Cloud Map 创建私有集成，请创建 HTTP 代理集成，指定要使用的 VPC 链接，并提供 AWS Cloud Map 服务的 ARN。

以下 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令创建私有集成，该集成通过 AWS Cloud Map 服务发现来识别资源。

```
aws apigatewayv2 create-integration --api-id api-id --integration-type HTTP_PROXY  \
    --integration-method GET --connection-type VPC_LINK \
    --connection-id VPC-link-ID \
    --integration-uri arn:aws:servicediscovery:us-east-2:123456789012:service/srv-id?stage=prod&deployment=green_deployment
    --payload-format-version 1.0
```

# 为 API Gateway 中的 HTTP API 配置 CORS
<a name="http-api-cors"></a>

[跨源资源共享 (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 是一项浏览器安全特征，该特征限制从在浏览器中运行的脚本启动的 HTTP 请求。如果您无法访问自己的 API 并收到包含 `Cross-Origin Request Blocked` 的错误消息，则可能需要启用 CORS。有关更多信息，请参阅[什么是 CORS？](https://aws.amazon.com/what-is/cross-origin-resource-sharing/)。

通常需要 CORS 以构建 Web 应用程序来访问托管在不同域或源上的 API。您可以启用 CORS 以允许从托管在不同域上的 Web 应用程序发出对 API 的请求。例如，如果您的 API 托管在 `https://{api_id}.execute-api.{region}.amazonaws.com/` 上，并且您希望从托管在 `example.com` 上的 Web 应用程序调用 API，您的 API 必须支持 CORS。

如果您为 API 配置 CORS，即使没有为 API 配置 OPTIONS 路由，API Gateway 也会自动向预检 OPTIONS 请求发送响应。对于 CORS 请求，API Gateway 将已配置的 CORS 标头添加到来自集成的响应中。

**注意**  
如果您为 API 配置 CORS，则 API Gateway 忽略从后端集成返回的 CORS 标头。

您可以在 CORS 配置中指定以下参数。要使用 API Gateway HTTP API 控制台添加这些参数，请在输入值后选择**添加**。


| CORS 标头 | CORS 配置属性 | 示例值 | 
| --- | --- | --- | 
|  Access-Control-Allow-Origin  |  allowOrigins  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/http-api-cors.html)  | 
|  Access-Control-Allow-Credentials  |  allowCredentials  |  true  | 
|  Access-Control-Expose-Headers  |  exposeHeaders  |  date、x-api-id、\$1  | 
|  Access-Control-Max-Age  |  maxAge  |  300  | 
|  Access-Control-Allow-Methods  |  allowMethods  |  GET、POST、DELETE\$1  | 
|  Access-Control-Allow-Headers  |  allowHeaders  |  authorization、\$1  | 

要返回 CORS 标头，您的请求必须包含 `origin` 标头。对于 `OPTIONS` 方法，您的请求必须包含 `origin` 标头和 `Access-Control-Request-Method` 标头。

您的 CORS 配置可能类似以下内容：

![\[HTTP API 的 CORS 配置\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/http-cors-console.png)


## 使用 `$default` 路由和授权方为 HTTP API 配置 CORS
<a name="http-api-cors-default-route"></a>

您可以为 HTTP API 的任何路由启用 CORS 并配置授权。当您为 [`$default` 路由](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-routes.html#http-api-develop-routes.default)启用 CORS 和授权时，需要注意一些特殊事项。`$default` 路由捕获对所有尚未显式定义的方法和路由的请求，包括 `OPTIONS` 请求。要支持未经授权的 `OPTIONS` 请求，请向 API 添加一条不需要授权的 `OPTIONS /{proxy+}` 路由，并向该路由附加一个集成。`OPTIONS /{proxy+}` 路由的优先级高于 `$default` 路由。因此，它允许客户端在未经授权的情况下向您的 API 提交 `OPTIONS` 请求。有关路由优先级的更多信息，请参阅 [路由 API 请求](http-api-develop-routes.md#http-api-develop-routes.evaluation)。

## 使用 AWS CLI 为 HTTP API 配置 CORS
<a name="http-api-cors.example"></a>

以下 [update-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-api.html) 命令启用来自 `https://www.example.com` 的 CORS 请求。

**Example**  

```
aws apigatewayv2 update-api --api-id api-id --cors-configuration AllowOrigins="https://www.example.com"
```

有关更多信息，请参阅 Amazon API Gateway 版本 2 API 参考中的 [CORS](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid.html#apis-apiid-model-cors)。

# 针对 API Gateway 中的 HTTP API 转换 API 请求和响应
<a name="http-api-parameter-mapping"></a>

您可以在客户端 API 请求到达后端集成之前修改它们。您还可以在 API Gateway 将响应返回给客户端之前更改集成的响应。您可以使用*参数映射*修改 HTTP API 的 API 请求和响应。要使用参数映射，您需要指定要修改的 API 请求或响应参数，并指定如何修改这些参数。



## 转换 API 请求
<a name="http-api-mapping-request-parameters"></a>

在请求到达后端集成之前，您可以使用请求参数更改请求。您可以修改标头、查询字符串或请求路径。

请求参数是键值映射。键用于标识要更改的请求参数的位置以及如何更改它。值指定参数的新数据。

下表显示了支持的键。


| 类型 | 语法 | 
| --- | --- | 
| 标头 | append\$1overwrite\$1remove:header.headername | 
| 查询字符串 | append\$1overwrite\$1remove:querystring.querystring-name | 
| 路径 | overwrite:path | 

下表显示了可以映射到参数的支持值。


| 类型 | 语法 | 备注 | 
| --- | --- | --- | 
| 标头值 | \$1request.header.name 或 \$1\$1request.header.name\$1 | 标头名称不区分大小写。API Gateway 将多个标头值与逗号组合在一起，例如 "header1": "value1,value2"。保留一些标头。要了解更多信息，请参阅“[保留的标头](#http-api-mapping-reserved-headers)”。 | 
| 查询字符串值 | \$1request.querystring.name 或 \$1\$1request.querystring.name\$1 | 查询字符串名称区分大小写。API Gateway 将多个值与逗号组合在一起，例如 "querystring1" "Value1,Value2"。 | 
| 请求正文 | \$1request.body.name 或 \$1\$1request.body.name\$1 | JSON 路径表达式 不支持递归下降 (\$1request.body..name) 和筛选表达式 (?(expression))。 当您指定 JSON 路径时，API Gateway 会在请求正文的 100 KB 处将其截断，然后应用选择表达式。要发送大于 100 KB 的负载，请指定 `$request.body`。  | 
| 请求路径 | \$1request.path 或 \$1 \$1request.path\$1 | 请求路径，没有阶段名称。 | 
| 路径参数 | \$1request.path.name 或 \$1\$1request.path.name\$1 | 请求中路径参数的值。例如，如果路由为 /pets/\$1petId\$1，则可以从具有 petId 的请求中映射 \$1request.path.petId 参数。 | 
| 上下文变量 | \$1context.variableName 或 \$1\$1context.variableName\$1 | [上下文变量](http-api-logging-variables.md)的值。仅支持特殊字符 `.` 和 `_`。 | 
| 阶段变量 | \$1stageVariables.variableName 或 \$1\$1stageVariables.variableName\$1 | [阶段变量](http-api-stages.stage-variables.md)的值。 | 
| 静态值 | string | 常量值。 | 

**注意**  
要在选择表达式中使用多个变量，请将该变量括在括号中。例如，`${request.path.name} ${request.path.id}`。

## 转换 API 响应
<a name="http-api-mapping-response-parameters"></a>

在将响应返回给客户端之前，您可以使用响应参数转换来自后端集成的 HTTP 响应。在 API Gateway 将响应返回给客户端之前，您可以修改响应的标头或状态码。

您可以为集成返回的每个状态代码配置响应参数。响应参数是键值映射。键用于标识要更改的请求参数的位置以及如何更改它。值指定参数的新数据。

下表显示了支持的键。


| 类型 | 语法 | 
| --- | --- | 
| 标头 | append\$1overwrite\$1remove:header.headername | 
| 状态代码 | overwrite:statuscode | 

下表显示了可以映射到参数的支持值。


| 类型 | 语法 | 备注 | 
| --- | --- | --- | 
| 标头值 | \$1response.header.name 或 \$1\$1response.header.name\$1 | 标头名称不区分大小写。API Gateway 将多个标头值与逗号组合在一起，例如 "header1": "value1,value2"。保留一些标头。要了解更多信息，请参阅“[保留的标头](#http-api-mapping-reserved-headers)”。 | 
| 响应正文 | \$1response.body.name 或 \$1\$1response.body.name\$1 | JSON 路径表达式。不支持递归下降 (\$1response.body..name) 和筛选表达式 (?(expression))。 当您指定 JSON 路径时，API Gateway 会在响应正文的 100 KB 处将其截断，然后应用选择表达式。要发送大于 100 KB 的负载，请指定 `$response.body`。  | 
| 上下文变量 | \$1context.variableName 或 \$1\$1context.variableName\$1 | 受支持的[上下文变量](http-api-logging-variables.md)的值。 | 
| 阶段变量 | \$1stageVariables.variableName 或 \$1\$1stageVariables.variableName\$1 | [阶段变量](http-api-stages.stage-variables.md)的值。 | 
| 静态值 | string | 常量值。 | 

**注意**  
要在选择表达式中使用多个变量，请将该变量括在括号中。例如，`${request.path.name} ${request.path.id}`。

## 保留的标头
<a name="http-api-mapping-reserved-headers"></a>

保留以下标头。您无法为这些标头配置请求或响应映射。
+ access-control-\$1
+ apigw-\$1
+ 授权
+ Connection
+ Content-Encoding
+ 内容长度
+ Content-Location
+ 已转发
+ Keep-Alive
+ Origin
+ Proxy-Authenticate
+ Proxy-Authorization
+ TE
+ Trailers 
+ Transfer-Encoding
+ 升级
+ x-amz-\$1
+ x-amzn-\$1
+ X-Forwarded-For
+ X-Forwarded-Host
+ X-Forwarded-Proto
+ Via

## 示例
<a name="http-api-parameter-mapping-examples"></a>

以下 AWS CLI 示例会配置参数映射。如需示例 CloudFormation 模板，请参阅 [GitHub](https://github.com/awsdocs/amazon-api-gateway-developer-guide/tree/main/cloudformation-templates)。

### 向 API 请求添加标头
<a name="http-api-parameter-mapping-examples-request-header"></a>

以下 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令在 API 请求到达后端集成之前，为请求创建名为 `header1` 的标头。API Gateway 使用请求 ID 填充标头。

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-type HTTP_PROXY \
    --payload-format-version 1.0 \
    --integration-uri 'https://api.example.com' \
    --integration-method ANY \
    --request-parameters '{ "append:header.header1": "$context.requestId" }'
```

### 重命名请求标头
<a name="http-api-parameter-mapping-examples-response"></a>

以下 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令将请求标头从 `header1` 重命名为 `header2`：

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-type HTTP_PROXY \
    --payload-format-version 1.0 \
    --integration-uri 'https://api.example.com' \
    --integration-method ANY \
    --request-parameters '{ "append:header.header2": "$request.header.header1",  "remove:header.header1": "''"}'
```

### 更改集成的响应
<a name="http-api-parameter-mapping-examples-response"></a>

以下 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令为集成配置响应参数。当集成返回 500 状态码时，API Gateway 会将状态码更改为 403，然后在响应中添加 `header1`1。当集成返回 404 状态码时，API Gateway 会向响应添加 `error` 标头。

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-type HTTP_PROXY \
    --payload-format-version 1.0 \
    --integration-uri 'https://api.example.com' \
    --integration-method ANY \
    --response-parameters '{"500" : {"append:header.header1": "$context.requestId", "overwrite:statuscode" : "403"}, "404" : {"append:header.error" : "$stageVariables.environmentId"}  }'
```

### 删除配置的参数映射
<a name="http-api-parameter-mapping-examples-remove"></a>

以下 [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令删除以前为 `append:header.header1` 配置的请求参数。它还删除了先前为 200 状态码配置的响应参数。

```
aws apigatewayv2 update-integration \
    --api-id abcdef123 \
    --integration-id hijk456 \
    --request-parameters '{"append:header.header1" : ""}' \
    --response-parameters '{"200" : {}}'
```

# 将 OpenAPI 定义用于 API Gateway 中的 HTTP API
<a name="http-api-open-api"></a>

您可以使用 OpenAPI 3.0 定义文件来定义您的 HTTP API。然后，您可以将定义导入 API Gateway 中以创建 API。要了解有关 OpenAPI 的 API Gateway 扩展的更多信息，请参阅 [适用于 API Gateway 的 OpenAPI 扩展](api-gateway-swagger-extensions.md)。

## 导入 HTTP API
<a name="http-api-import"></a>

您可以通过导入 OpenAPI 3.0 定义文件来创建 HTTP API。

要从 REST API 迁移到 HTTP API，您可以将 REST API 导出为 OpenAPI 3.0 定义文件。然后，将 API 定义导入为 HTTP API。要了解有关导出 REST API 的更多信息，请参阅 [从 API Gateway 导出 REST API](api-gateway-export-api.md)。

**注意**  
HTTP API 与 REST API 支持相同的AWS变量。要了解更多信息，请参阅“[用于 OpenAPI 导入的 AWS 变量](import-api-aws-variables.md)”。

### 导入验证信息
<a name="http-api-import.validation"></a>

导入 API 时，API Gateway 提供三类验证信息。

**Info**  
根据 OpenAPI 规范，属性是有效的，但对于 HTTP API 不支持该属性。  
例如，以下 OpenAPI 3.0 代码段生成有关导入的信息，因为 HTTP API 不支持请求验证。API Gateway 忽略 `requestBody` 和 `schema` 字段。  

```
"paths": {
  "/": {
    "get": {
      "x-amazon-apigateway-integration": {
        "type": "AWS_PROXY",
        "httpMethod": "POST",
        "uri": "arn:aws:lambda:us-east-2:123456789012:function:HelloWorld",
        "payloadFormatVersion": "1.0"
      },
      "requestBody": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Body"
            }
          }
        }
      }
    }
  }
  ...
},
"components": {
  "schemas": {
    "Body": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string"
        }
      }
    }
    ...
  }
  ...
}
```

**警告**  
根据 OpenAPI 规范，属性或结构是无效的，但它不会阻止 API 创建。您可以指定 API Gateway 是应忽略这些警告并继续创建 API，还是在出现警告时停止创建 API。  
以下 OpenAPI 3.0 文档在导入时生成警告，因为 HTTP API 只支持 Lambda 代理和 HTTP 代理集成。  

```
"x-amazon-apigateway-integration": {
  "type": "AWS",
  "httpMethod": "POST",
  "uri": "arn:aws:lambda:us-east-2:123456789012:function:HelloWorld",
  "payloadFormatVersion": "1.0"
}
```

**错误**  
OpenAPI 规范无效或格式错误。API Gateway 无法从格式错误的文档创建任何资源。您必须修复错误，然后重试。  
以下 API 定义会在导入时产生错误，因为 HTTP API 只支持 OpenAPI 3.0 规范。  

```
{
  "swagger": "2.0.0",
  "info": {
    "title": "My API",
    "description": "An Example OpenAPI definition for Errors/Warnings/ImportInfo",
    "version": "1.0"
  }
  ...
}
```
在另一个示例中，虽然 OpenAPI 允许用户定义一个具有与特定操作相关的多个安全要求的 API，但 API Gateway 不支持这一点。每个操作只能有一个 IAM 授权、一个 Lambda 授权者或一个 JWT 授权者。尝试对多个安全要求进行建模会导致错误。

### 使用 AWS CLI 导入 API
<a name="http-api-import.example"></a>

以下 [import-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/import-api.html) 命令将 OpenAPI 3.0 定义文件 `api-definition.json` 导入为 HTTP API。

**Example**  

```
aws apigatewayv2 import-api --body file://api-definition.json
```

**Example**  
您可以导入以下示例 OpenAPI 3.0 定义来创建 HTTP API。  

```
{
  "openapi": "3.0.1",
  "info": {
    "title": "Example Pet Store",
    "description": "A Pet Store API.",
    "version": "1.0"
  },
  "paths": {
    "/pets": {
      "get": {
        "operationId": "GET HTTP",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pets"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP_PROXY",
          "httpMethod": "GET",
          "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets",
          "payloadFormatVersion": 1.0
        }
      },
      "post": {
        "operationId": "Create Pet",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewPet"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewPetResponse"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP_PROXY",
          "httpMethod": "POST",
          "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets",
          "payloadFormatVersion": 1.0
        }
      }
    },
    "/pets/{petId}": {
      "get": {
        "operationId": "Get Pet",
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pet"
                }
              }
            }
          }
        },        
        "x-amazon-apigateway-integration": {
          "type": "HTTP_PROXY",
          "httpMethod": "GET",
          "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets/{petId}",
          "payloadFormatVersion": 1.0
        }
      }
    }
  },
  "x-amazon-apigateway-cors": {
    "allowOrigins": [
      "*"
    ],
    "allowMethods": [
      "GET",
      "OPTIONS",
      "POST"
    ],
    "allowHeaders": [
      "x-amzm-header",
      "x-apigateway-header",
      "x-api-key",
      "authorization",
      "x-amz-date",
      "content-type"
    ]
  },
  "components": {
    "schemas": {
      "Pets": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/Pet"
        }
      },
      "Empty": {
        "type": "object"
      },
      "NewPetResponse": {
        "type": "object",
        "properties": {
          "pet": {
            "$ref": "#/components/schemas/Pet"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Pet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "price": {
            "type": "number"
          }
        }
      },
      "NewPet": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/PetType"
          },
          "price": {
            "type": "number"
          }
        }
      },
      "PetType": {
        "type": "string",
        "enum": [
          "dog",
          "cat",
          "fish",
          "bird",
          "gecko"
        ]
      }
    }
  }
}
```

# 从 API Gateway 导出 HTTP API
<a name="http-api-export"></a>

创建 HTTP API 后，您可以从 API Gateway 导出 API 的 OpenAPI 3.0 定义。您可以选择要导出的阶段，也可以导出 API 的最新配置。还可以将导出的 API 定义导入到 API Gateway 中，以创建另一个相同的 API。要了解有关导入 API 定义的更多信息，请参阅 [导入 HTTP API](http-api-open-api.md#http-api-import)。

## 使用AWS CLI 导出阶段的 OpenAPI 3.0 定义
<a name="http-api-export.stage.example"></a>

以下 [export-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/export-api.html) 命令将名为 `prod` 的 API 阶段的 OpenAPI 定义，导出到名为 `stage-definition.yaml` 的 YAML 文件。默认情况下，导出的定义文件包含 [API Gateway 扩展名](api-gateway-swagger-extensions.md)。

```
aws apigatewayv2 export-api \
    --api-id api-id  \
    --output-type YAML  \
    --specification OAS30 \
    --stage-name prod \
    stage-definition.yaml
```

## 使用AWS CLI 导出 API 的最新更改的 OpenAPI 3.0 定义
<a name="http-api-export.latest.example"></a>

以下 [export-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/export-api.html) 命令将 HTTP API 的 OpenAPI 定义导出到名为 `latest-api-definition.json` 的 JSON 文件。由于命令未指定阶段，因此 API Gateway 导出 API 的最新配置，无论它是否已部署到阶段。导出的定义文件不包含 [API Gateway 扩展名](api-gateway-swagger-extensions.md)。

```
aws apigatewayv2 export-api \
    --api-id api-id  \
    --output-type JSON  \
    --specification OAS30 \
    --no-include-extensions \
    latest-api-definition.json
```

有关更多信息，请参阅 *Amazon API Gateway 版本 2 API 参考* 中的 [ExportAPI](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-exports-specification.html#apis-apiid-exports-specification-http-methods)。

## 使用 API Gateway 控制台导出 OpenAPI 3.0 定义
<a name="http-api-export.console"></a>

以下过程显示了如何导出 HTTP API 的 OpenAPI 定义。

**使用 API Gateway 控制台导出 OpenAPI 3.0 定义**

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

1. 选择 HTTP API。

1. 在主导航窗格的**开发**下，选择**导出**。

1. 在以下选项中选择，以导出您的 API：  
![\[HTTP API 的导出选项。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/export-http-api.png)

   1. 在**来源**中，选择 OpenAPI 3.0 定义的来源。您可以选择要导出的阶段，也可以导出 API 的最新配置。

   1. 打开**包括 API Gateway 扩展**以包含 [API 网关扩展](api-gateway-swagger-extensions.md)。

   1. 在**输出格式**中，选择一种输出格式。

1. 选择**下载**。

# 发布 HTTP API 供客户调用
<a name="http-api-publish"></a>

您可以使用阶段和自定义域名发布 API 以供客户端调用。

一个 API 阶段是对您 API 生命周期状态（例如，`dev`、`prod`、`beta` 或 `v2`）的一次逻辑引用。每个阶段都是一个对 API 部署的命名引用，可供客户端应用程序调用。您可以为 API 的每个阶段配置不同的集成和设置。

您可以使用自定义域名来提供比默认 URL `https://api-id.execute-api.region.amazonaws.com/stage` 更简单、更直观的 URL，以供客户端调用 API。

**注意**  
为了增强您的 API Gateway API 的安全性，将在[公共后缀列表 (PSL)](https://publicsuffix.org/) 中注册 `execute-api.{region}.amazonaws.com` 域。为进一步增强安全性，如果您需要在 API Gateway API 的默认域名中设置敏感 Cookie，我们建议您使用带 `__Host-` 前缀的 Cookie。这将有助于保护您的域，防范跨站点请求伪造 (CSRF) 攻击。要了解更多信息，请参阅 Mozilla 开发者网络中的 [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) 页面。

**Topics**
+ [针对 API Gateway 中 HTTP API 的阶段](http-api-stages.md)
+ [API Gateway 中的 HTTP API 的安全策略](http-api-ciphers.md)
+ [API Gateway 中的 HTTP API 的自定义域名](http-api-custom-domain-names.md)

# 针对 API Gateway 中 HTTP API 的阶段
<a name="http-api-stages"></a>

一个 API 阶段是对您 API 生命周期状态（例如，`dev`、`prod`、`beta` 或 `v2`）的一次逻辑引用。API 阶段通过 API ID 和阶段名称标识，包含在您用于调用 API 的 URL 中。每个阶段都是一个对 API 部署的命名引用，可供客户端应用程序调用。

您可以创建一个 `$default` 阶段，该阶段可以从 API 的 URL 的基本部分得出 — 例如 `https://{api_id}.execute-api.{region}.amazonaws.com/`。您可以使用此 URL 调用 API 阶段。

部署是 API 配置的快照。将 API 部署到阶段后，客户端可以调用该 API。您必须部署 API 才能使更改生效。如果启用自动部署，则会自动为您发布对 API 的更改。

# 对 API Gateway 中的 HTTP API 使用阶段变量
<a name="http-api-stages.stage-variables"></a>

阶段变量是您可以为 HTTP API 的阶段定义的键/值对。它们与环境变量的功能类似，可用于 API 设置。

阶段变量不适用于敏感数据，例如凭证。要将敏感数据传递给集成，请使用 AWS Lambda 授权方。您可以在 Lambda 授权方的输出中将敏感数据传递给集成。要了解更多信息，请参阅“[Lambda 授权方响应格式](http-api-lambda-authorizer.md#http-api-lambda-authorizer.payload-format-response)”。

## 示例 – 使用阶段变量自定义 HTTP 集成端点
<a name="http-api-stages.stage-variables-examples"></a>

例如，您可以定义阶段变量，然后将其值设置为某个 HTTP 代理集成的 HTTP 端点。稍后，您可以使用关联的阶段变量名称引用端点。通过执行此操作，您可以在各个阶段对不同端点使用相同的 API 设置。同样，您可以使用阶段变量，为 API 的各个阶段指定不同的 AWS Lambda 函数集成。

要使用阶段变量自定义 HTTP 集成端点，您必须首先设置阶段变量的名称和值（例如 `url`，值为 `example.com`）。接下来，设置 HTTP 代理集成。您可以告知 API Gateway 使用阶段变量值 **http://\$1\$1stageVariables.url\$1**，而不是输入端点的 URL。此值将指示 API Gateway 在运行时替换您的阶段变量 `${}`，具体取决于 API 所处的阶段。

您可以通过类似的方式引用阶段变量，用于指定 Lambda 函数名称或AWS角色 ARN。

将 Lambda 函数名称指定为阶段变量值时，您必须手动配置对 Lambda 函数的权限。以下 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令配置 Lambda 函数的权限：

```
aws lambda add-permission --function-name arn:aws:lambda:XXXXXX:your-lambda-function-name --source-arn arn:aws:execute-api:us-east-1:YOUR_ACCOUNT_ID:api_id/*/HTTP_METHOD/resource --principal apigateway.amazonaws.com --statement-id apigateway-access --action lambda:InvokeFunction
```

# API Gateway 中的 HTTP API 的 API Gateway 阶段变量引用
<a name="http-api-stages.stage-variables-reference"></a>

在以下情况下，您可以对 HTTP API 使用 API Gateway 阶段变量。

## HTTP 集成 URI
<a name="http-api-stages.stage-variables-in-integration-HTTP-uris"></a>

您可将阶段变量用作 HTTP 集成 URI 的一部分，如以下示例所示。
+ 不带协议的完整 URI – `http://${stageVariables.<variable_name>}`
+ 完整域 – `http://${stageVariables.<variable_name>}/resource/operation`
+ 子域 – `http://${stageVariables.<variable_name>}.example.com/resource/operation`
+ 路径 – `http://example.com/${stageVariables.<variable_name>}/bar`
+ 查询字符串 – `http://example.com/foo?q=${stageVariables.<variable_name>}` 

## Lambda 函数
<a name="http-api-stages.stage-variables-in-integration-lambda-functions"></a>

 您可以使用阶段变量代替 Lambda 函数集成名称或别名，如以下示例所示。
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations`
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations`

**注意**  
要将阶段变量用于 Lambda 函数，该函数必须与 API 位于同一账户中。阶段变量不支持跨账户 Lambda 函数。

## AWS 集成凭证
<a name="http-api-stages.stage-variables-in-integration-aws-credentials"></a>

 您可以在 AWS 用户或角色凭证 ARN 中使用阶段变量，如以下示例所示。
+  `arn:aws:iam::<account_id>:${stageVariables.<variable_name>}` 

# API Gateway 中的 HTTP API 的安全策略
<a name="http-api-ciphers"></a>

API Gateway 对所有 HTTP API 端点强制执行 `TLS_1_2` 的安全策略。

*安全策略* 是 Amazon API Gateway 提供的最低 TLS 版本和密码套件的预定义组合。TLS 协议解决了网络安全问题，例如客户端和服务器之间的篡改和窃听。当您的客户端通过自定义域建立与您 API 的 TLS 握手时，安全策略实施客户端可以选择使用的 TLS 版本和密码套件选项。此安全策略接受 TLS 1.2 和 TLS 1.3 流量并拒绝 TLS 1.0 流量。

## HTTP API 支持的 TLS 协议和密码
<a name="http-api-ciphers-list"></a>

下表描述了 HTTP API 支持的 TLS 协议。


| **TLS 协议** | **TLS\$11\$10 安全策略** | 
| --- | --- | 
| TLSv1.3 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| TLSv1.2 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 

下表描述了适用于 HTTP API 的 TLS 1\$12 安全策略的 TLS 密码。


| **TLS 密码** | **TLS\$11\$10 安全策略** | 
| --- | --- | 
| TLS-AES-128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| TLS-AES-256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| TLS-CHACHA20-POLY1305-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES128- GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES128- GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES256- GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES256- GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES256-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES256-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES256-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/success_icon.svg) 是 | 

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

OpenSSL 和 IETF RFC 5246 为相同的密码使用不同的名称。有关密码名称的列表，请参阅[OpenSSL 和 RFC 密码名称](apigateway-security-policies-list.md#apigateway-secure-connections-openssl-rfc-cipher-names)。

## 有关 REST API 和 WebSocket API 的信息
<a name="apigateway-http-additional-apis"></a>

有关 REST API 和 WebSocket API 的更多信息，请参阅[选择针对 API Gateway 中自定义域的安全策略](apigateway-custom-domain-tls-version.md)和[针对 API Gateway 中的 WebSocket API 的安全策略](websocket-api-ciphers.md)。

# API Gateway 中的 HTTP API 的自定义域名
<a name="http-api-custom-domain-names"></a>

*自定义域名* 是您可以提供给 API 用户的更简单、更直观的 URL。

部署 API 后，您（和您的客户）可以使用以下格式的默认基本 URL 调用 API：

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

其中 *api-id* 由 API Gateway 生成，*region* 是 AWS 区域，*stage* 由您在部署 API 时指定。

URL 的主机名部分（即 `api-id.execute-api.region.amazonaws.com`）是指 API 端点。默认 API 端点名称是随机生成的，难以重新调用，对用户不友好。

使用自定义域名，您可以设置 API 的主机名，并选择基本路径（例如 `myservice`）以将备用 URL 映射到 API。例如，一个更为用户友好的 API 基本 URL 可以变成：

```
https://api.example.com/myservice
```

## 注意事项
<a name="http-api-custom-domain-name-considerations"></a>

以下注意事项可能会影响您对自定义域名的使用。
+ 区域自定义域名可以与 REST API 和 HTTP API 相关联。您可以使用 API Gateway 版本 2 API 为 REST API 创建和管理区域自定义域名。
+ 对于最低 TLS 版本，仅支持 TLS 1.2。
+ 您必须创建或更新 DNS 提供程序的资源记录以映射到您的 API 端点。如果没有此类映射，针对自定义域名的 API 请求无法到达 API Gateway。
+ 您可以使用通配符证书，在不超过默认配额的情况下支持几乎无限数量的域名。有关更多信息，请参阅 [通配符自定义域名](#http-wildcard-custom-domain-names)。

## 先决条件
<a name="http-api-custom-domain-names-prerequisites"></a>

以下是创建自定义域名的先决条件：

### 注册域名
<a name="http-api-custom-domain-names-register"></a>

您必须拥有已注册的 Internet 域名，以便为 API 设置自定义域名。您可以使用 [Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/) 或使用您选择的第三方域注册商注册互联网域名。自定义域名可以是注册的互联网域的子域或根域（也称为“机构根网域”）名称。

域名必须遵循 [RFC 1035](https://tools.ietf.org/html/rfc1035#section-2.3.4) 规范，每个标签最多可以有 63 个八位字节，总共可以有 255 个八位字节。

### 自定义域名的证书
<a name="http-api-custom-domain-names-certificates"></a>

为 API 设置自定义域名之前，您必须先在 ACM 中准备好 SSL/TLS 证书。如果 ACM 在您要创建自定义域名的 AWS 区域中不可用，您必须将证书导入到该区域的 API Gateway。

要导入 SSL/TLS 证书，您必须针对自定义域名提供 PEM 格式的 SSL/TLS 证书文本、其私有密钥和证书链。

存储在 ACM 中的每个证书均由其 ARN 标识。如果拥有 ACM 颁发的证书，那么您就无需担心公开任何敏感的证书详细信息，如私有密钥。要针对域名使用 AWS 托管的证书，您只需参考其 ARN 即可。

如果您的应用程序使用证书固定（有时称为 SSL 固定）来固定 ACM 证书，则在 AWS 续订证书后，应用程序可能无法连接到您的域。有关更多信息，请参阅《AWS Certificate Manager 用户指南》**中的[证书固定问题](https://docs.aws.amazon.com/acm/latest/userguide/troubleshooting-pinning.html)。

## 通配符自定义域名
<a name="http-wildcard-custom-domain-names"></a>

使用通配符自定义域名，您可以在不超过[默认配额](limits.md)的情况下支持几乎无限数量的域名。例如，您可以为每位客户提供自己的域名 `customername.api.example.com`。

要创建通配符自定义域名，可以指定通配符 (`*`) 作为表示根域所有可能子域的自定义域的第一个子域。

例如，通配符自定义域名 `*.example.com` 会生成子域，如 `a.example.com`、`b.example.com` 和 `c.example.com`，这些子域都会路由到同一个域。

通配符自定义域名支持与 API Gateway 的标准自定义域名不同的配置。例如，在单个 AWS 账户中，您可以对 `*.example.com` 和 `a.example.com` 进行不同的配置。

要创建通配符自定义域名，您必须提供已使用 DNS 或电子邮件验证方法验证的由 ACM 颁发的证书。

**注意**  
如果其他 AWS 账户已经创建了与通配符自定义域名冲突的自定义域名，则无法创建通配符自定义域名。例如，如果账户 A 已经创建了 `a.example.com`，则账户 B 无法创建通配符自定义域名 `*.example.com`。  
如果账户 A 和账户 B 共享拥有者，您可以联系 [AWS Support 中心](https://console.aws.amazon.com/support/home#/)请求例外。

## 自定义域名的后续步骤
<a name="http-api-custom-domain-names-next-steps"></a>

要为 HTTP API 设置自定义域名，您可以使用《API Gateway 开发人员指南》中的“REST API”部分的文档。

首先，为自定义域名指定一个证书。有关更多信息，请参阅 [在 AWS Certificate Manager 中准备好证书](how-to-specify-certificate-for-custom-domain-name.md)。然后，创建一个区域性自定义域名。有关更多信息，请参阅 [在 API Gateway 中设置区域自定义域名](apigateway-regional-api-custom-domain-create.md)。

# 将 API 阶段映射到 HTTP API 的自定义域名
<a name="http-api-mappings"></a>

您可以使用 API 映射将 API 阶段连接到自定义域名。创建域名并配置 DNS 记录后，您可以使用 API 映射通过自定义域名向 API 发送流量。

API 映射指定了用于映射的 API、阶段以及可选的路径。例如，您可以将 API 的 `production` 阶段映射到 `https://api.example.com/orders`。

您可以将 HTTP 和 REST API 阶段映射到相同的自定义域名。

在创建 API 映射之前，您必须拥有 API、阶段和自定义域名。要了解有关创建自定义域名的更多信息，请参阅 [在 API Gateway 中设置区域自定义域名](apigateway-regional-api-custom-domain-create.md)。

## 路由 API 请求
<a name="http-api-mappings-evalutation"></a>

您可以使用多个级别配置 API 映射，例如 `orders/v1/items` 和 `orders/v2/items`。

对于具有多个级别的 API 映射，API Gateway 将请求路由到匹配路径最长的 API 映射。选择要调用的 API 时，API Gateway 仅考虑为 API 映射配置的路径，而不考虑 API 路由。如果没有与请求匹配的路径，API Gateway 会将请求发送到已映射到空路径 `(none)` 的 API。

对于使用具有多个级别的 API 映射的自定义域名，API Gateway 将请求路由到匹配前缀最长的 API 映射。

例如，考虑使用以下 API 映射的自定义域名 `https://api.example.com`：

1. `(none)` 映射到 API 1。

1. `orders` 映射到 API 2。

1. `orders/v1/items` 映射到 API 3。

1. `orders/v2/items` 映射到 API 4。

1. `orders/v2/items/categories` 映射到 API 5。


| 请求 | 选定的 API | 说明 | 
| --- | --- | --- | 
|  `https://api.example.com/orders`  |  `API 2`  |  请求完全匹配此 API 映射。  | 
|  `https://api.example.com/orders/v1/items`  |  `API 3`  |  请求完全匹配此 API 映射。  | 
|  `https://api.example.com/orders/v2/items`  |  `API 4`  |  请求完全匹配此 API 映射。  | 
|  `https://api.example.com/orders/v1/items/123`  |  `API 3`  |  API Gateway 选择匹配路径最长的映射。请求结尾处的 `123` 不影响选择。  | 
|  `https://api.example.com/orders/v2/items/categories/5`  |  `API 5`  |  API Gateway 选择匹配路径最长的映射。  | 
|  `https://api.example.com/customers`  |  `API 1`  |  API Gateway 使用空映射作为“捕获全部”。  | 
|  `https://api.example.com/ordersandmore`  |  `API 2`  |  API Gateway 选择匹配前缀最长的映射。 对于配置了单级映射的自定义域名（例如，仅 `https://api.example.com/orders` 和 `https://api.example.com/`），API Gateway 会选择 `API 1`，因为没有与 `ordersandmore` 匹配的路径。  | 

## 限制
<a name="http-api-mappings-restrictions"></a>
+ 在 API 映射中，自定义域名和映射的 API 必须位于同一个AWS账户中。
+ API 映射必须仅包含字母、数字和以下字符：`$-_.+!*'()/`。
+ API 映射中路径的最大长度为 300 个字符。
+ 每个域名可以有 200 个具有多个级别的 API 映射。此限制不包括单级的 API 映射，例如 `/prod`。
+ 您只能使用 TLS 1.2 安全策略将 HTTP API 映射到区域自定义域名。
+ 您不能将 WebSocket API 映射到与 HTTP API 或 REST API 相同的自定义域名。
+ 如果您创建具有多个级别的 API 映射，API Gateway 会将所有标头名称转换为小写。

## 创建 API 映射
<a name="http-api-mappings-examples"></a>

要创建 API 映射，您必须首先创建自定义域名、API 和阶段。有关使用自定义域名的更多信息，请参阅 [在 API Gateway 中设置区域自定义域名](apigateway-regional-api-custom-domain-create.md)。

例如，创建所有资源的 AWS Serverless Application Model 模板，请参阅 GitHub 上的[使用 SAM 的会话](https://github.com/aws-samples/sessions-with-aws-sam/tree/master/custom-domains)。

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

**创建 API 映射**

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

1. 选择**自定义域名**。

1. 选择您已经创建的自定义域名。

1. 选择 **API 映射**。

1. 选择 **Configure API mappings (配置 API 映射)**。

1. 选择 **Add new mapping (添加新映射)**。

1. 输入 **API**、**阶段**以及可选的**路径**。

1. 选择**保存**。

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

使用以下 [create-api-mapping](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) 命令创建 API 映射。在此示例中，API Gateway 将请求发送到 `api.example.com/v1/orders`，到指定的 API 和阶段。

```
aws apigatewayv2 create-api-mapping \
    --domain-name api.example.com \
    --api-mapping-key v1/orders \
    --api-id a1b2c3d4 \
    --stage test
```

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

以下 CloudFormation 示例会创建一个 API 映射。

```
MyApiMapping:
  Type: 'AWS::ApiGatewayV2::ApiMapping'
  Properties:
    DomainName: api.example.com
    ApiMappingKey: 'orders/v2/items'
    ApiId: !Ref MyApi
    Stage: !Ref MyStage
```

------

# 禁用 REST API 的默认端点
<a name="http-api-disable-default-endpoint"></a>

默认情况下，客户端可以通过使用 API Gateway 为 API 生成的 `execute-api` 端点来调用您的 API。为确保客户端只能通过使用自定义域名访问您的 API，请禁用默认 `execute-api` 端点。禁用默认端点时，它会影响 API 的所有阶段。

以下过程演示了如何禁用 HTTP API 的默认端点。

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

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

1. 选择 HTTP API。

1. 选择 API 的 ID 以打开 **API 详细信息**页面。

1. 在 **API 详细信息**选项卡上，选择**编辑**。

1. 对于**默认端点**，选择**禁用**。

1. 选择**保存**。

   如果开启了阶段的自动部署，您无需重新部署 API 即可使更改生效。否则，您必须重新部署 API。

1. （可选）选择**部署**，然后重新部署您的 API 或创建一个新阶段使更改生效。

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

以下 [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) 命令禁用 HTTP API 的默认端点：

```
aws apigatewayv2 update-api \
    --api-id abcdef123 \
    --disable-execute-api-endpoint
```

禁用默认端点后，除非启用了自动部署，否则必须部署 API 才能使更改生效。

下面的 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-deployment.html) 命令将创建一个部署。

```
aws apigatewayv2 create-deployment \
    --api-id abcdef123 \
    --stage-name dev
```

------

# HTTP API 的自定义域名的 IP 地址类型
<a name="http-api-custom-domain-names-ip-address-type"></a>

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

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

以下注意事项可能会影响您对 IP 地址类型的使用。
+ API Gateway 自定义域名的默认 IP 地址类型是 IPv4。
+ 对于映射到自定义域名的所有 API，自定义域名不需要具有相同的 IP 地址类型。如果您禁用默认 API 端点，则这可能会影响调用方调用 API 的方式。

## 更改自定义域名的 IP 地址类型
<a name="http-api-custom-domain-names-ip-address-type-change"></a>

您可以通过更新域的端点配置来更改 IP 地址类型。您可以使用 AWS 管理控制台、AWS CLI、CloudFormation 或 AWS SDK 更新域的端点配置。

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

**更改自定义域名的 IP 地址类型**

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

1. 选择公有自定义域名。

1. 选择**端点配置**。

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

1. 选择**保存**。

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

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

```
aws apigatewayv2 update-domain-name \
   --domain-name dualstack.example.com \
   --domain-name-configurations CertificateArn=arn:aws:acm:us-east-1:111122223333:certificate/abcd1234-5678-abc,IpAddressType=dualstack
```

输出将与以下内容类似：

```
{
    "ApiMappingSelectionExpression": "$request.basepath",
    "DomainName": "dualstack.example.com",
    "DomainNameConfigurations": [
        {
            "ApiGatewayDomainName": "d-abcd1234.execute-api.us-east-1.amazonaws.com",
            "CertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/abcd1234-5678-abc",
            "DomainNameStatus": "AVAILABLE",
            "EndpointType": "REGIONAL",
            "HostedZoneId": "Z3LQWSYCGH4ADY",
            "SecurityPolicy": "TLS_1_2",
            "IpAddressType": "dualstack"
        }
    ],
    "Tags": {}
}
```

------

# 保护 API Gateway 中的 HTTP API
<a name="http-api-protect"></a>

API Gateway 提供了多种方法来保护您的 API 免受某些威胁，例如恶意用户或流量高峰。您可以使用诸如设置目标和启用双向 TLS 等策略来保护您的 API。在本节中，您可以了解如何使用 API Gateway 启用这些功能。

**Topics**
+ [在 API Gateway 中限制对 HTTP API 的请求以提高吞吐量](http-api-throttling.md)
+ [如何针对 API Gateway 中的 HTTP API 启用双向 TLS 身份验证](http-api-mutual-tls.md)

# 在 API Gateway 中限制对 HTTP API 的请求以提高吞吐量
<a name="http-api-throttling"></a>

您可以为 API 配置节流，以帮助防止它们因请求过多而不堪重负。节流是在尽最大努力的基础上应用的，应被视为目标而不是保证的请求上限。

API Gateway 使用令牌桶算法（其中，一个令牌即一个请求）限制对 API 的请求。具体来说，API Gateway 根据您账户中的所有 API，按区域检查请求提交的速率和突发事件。在令牌桶算法中，突发可以允许这些限制的预定义超出，但在某些情况下，其他因素也可能导致限制超支。

如果请求提交超过稳态请求速率和突增限制，则 API Gateway 将开始限制请求。此时客户可能会收到 `429 Too Many Requests` 个错误响应。捕获此类异常后，客户端能够以限制速率的方式重新提交失败的请求。

作为 API 开发人员，您可以针对各个 API 阶段或方法设置目标限制，以提高账户中所有 API 的整体性能。

## 每个区域的账户级别限制
<a name="http-api-protect-throttling-account"></a>

默认情况下，API Gateway 针对每个区域限制 AWS 账户内所有 API 的每秒稳态请求 (RPS)。它还对于每个区域限制一个 AWS 账户中所有 API 的突增（即最大存储桶大小）。在 API Gateway 中，突增限制代表 API Gateway 在返回 `429 Too Many Requests` 错误响应之前可以完成目标的最大并发请求提交数量。有关限制配额的更多信息，请参阅[Amazon API Gateway 配额](limits.md)。

每个账户限制适用于指定区域内账户中的所有 API。客户可以请求我们放宽账户级别的速率限制 —— 如果具有更短的超时和较小的有效负载的 API，则可以提高限制。要请求增加每个区域的账户级别限制，请联系 [AWS Support 中心](https://console.aws.amazon.com/support/home#/)。有关更多信息，请参阅 [Amazon API Gateway 配额](limits.md)。请注意，这些限制不能高于 AWS 节流限制。

## 路由级别限制
<a name="http-api-protect-throttling-route"></a>

您可以设置路由级别限制，用于覆盖 API 中特定阶段或各个路由的账户级别请求限制。原定设置的路由节流限制不能超过账户级别的费率限制。

您可以使用 AWS CLI 配置路由级限制。以下 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) 命令为 API 的指定阶段和路由配置自定义节流。

```
aws apigatewayv2 update-stage \
    --api-id a1b2c3d4 \
    --stage-name dev \
    --route-settings '{"GET /pets":{"ThrottlingBurstLimit":100,"ThrottlingRateLimit":2000}}'
```

# 如何针对 API Gateway 中的 HTTP API 启用双向 TLS 身份验证
<a name="http-api-mutual-tls"></a>

双向 TLS 身份验证要求在客户端和服务器之间进行双向身份验证。使用双向 TLS，客户端必须提供 X.509 证书来验证其身份才能访问您的 API。双向 TLS 是物联网 (IoT) 和企业对企业应用程序的常见要求。

您可以使用双向 TLS 以及 API Gateway 支持的其他[授权和身份验证操作](apigateway-control-access-to-api.md)。API Gateway 将客户端提供的证书转发给 Lambda 授权方和后端集成。

**重要**  
默认情况下，客户端可以通过使用 API Gateway 为 API 生成的 `execute-api` 终端节点来调用您的 API。要确保客户端只能通过使用具有双向 TLS 的自定义域名访问您的 API，请禁用默认 `execute-api` 端点。要了解更多信息，请参阅“[禁用 REST API 的默认端点](http-api-disable-default-endpoint.md)”。

## 使用双向 TLS 的先决条件
<a name="http-api-mutual-tls-prerequisites"></a>

要配置双向 TLS，您需要：
+ 自定义域名
+ 至少在 AWS Certificate Manager 中为您的自定义域名配置了一个证书
+ 已配置信任存储库并上载到 Amazon S3

### 自定义域名
<a name="http-api-mutual-tls-custom-domain-name"></a>

 要为 HTTP API 启用双向 TLS，您必须为 API 配置自定义域名。您可以为自定义域名启用双向 TLS，然后向客户端提供自定义域名。要使用启用了双向 TLS 的自定义域名访问 API，客户端必须提供您在 API 请求中信任的证书。您可以在 [API Gateway 中的 HTTP API 的自定义域名](http-api-custom-domain-names.md) 中找到更多信息。

### 使用 AWS Certificate Manager 颁发的证书
<a name="http-api-mutual-tls-using-acm-issued-certs"></a>

您可以直接从 ACM 请求公开可信的证书，也可以导入公开证书或自签名证书。要在 ACM 中设置证书，请前往 [ACM](https://console.aws.amazon.com/acm/)。如果要导入证书，请继续阅读以下部分中的内容。

### 使用导入的证书或 AWS 私有证书颁发机构 证书
<a name="http-api-mutual-tls-non-acm-certs"></a>

要使用导入至 ACM 中的证书或来自 AWS 私有证书颁发机构 的带有双向 TLS 的证书，API Gateway 需要由 ACM 颁发的 `ownershipVerificationCertificate`。此所有权证书仅用于验证您是否有权使用域名。它不用于 TLS 握手。如果您还没有 `ownershipVerificationCertificate`，请前往 [https://console.aws.amazon.com/acm/](https://console.aws.amazon.com/acm/) 来设置一个。

您需要确保此证书在域名生命周期内有效。如果证书过期且自动续订失败，则域名的所有更新都将被锁定。您需要使用有效 `ownershipVerificationCertificate` 更新 `ownershipVerificationCertificateArn`，然后才能进行任何其他更改。`ownershipVerificationCertificate` 不能用作 API Gateway 中另一个双向 TLS 域的服务器证书。如果直接向 ACM 中重新导入证书，发布者必须保持不变。

### 配置信任存储库
<a name="http-api-mutual-tls-create-trust-store"></a>

信任存储库是带有 `.pem` 文件扩展名的文本文件。它们是来自证书颁发机构的证书的受信任列表。要使用双向 TLS，请创建您信任的 X.509 证书的信任存储库以访问您的 API。

您必须在信任存储库中包含完整的信任链，从颁发的 CA 证书到根 CA 证书。API Gateway 接受信任链中存在的任何 CA 发布的客户端证书。证书可以来自公有或私有证书颁发机构。证书的最大链长度可为四。您还可以提供自签名证书。信任存储库支持以下哈希算法：
+ SHA-256 或更强
+ RSA-2048 或更强
+ ECDSA-256 或更强

API Gateway 验证许多证书属性。您可以使用 Lambda 授权方在客户端调用 API 时执行其他检查，包括检查证书是否已被吊销。API Gateway 验证以下属性：


| 验证 | 说明 | 
| --- | --- | 
|  X.509 语法  |  证书必须满足 X.509 语法要求。  | 
|  完整性  |  证书的内容不得与信任存储库中证书颁发机构签名的内容有所差异。  | 
|  有效性  |  证书的有效期必须是最新的。  | 
|  名称链接/键链接  |  证书的名称和主题必须形成一个完整的链条。证书的最大链长度可为四。  | 

### 以单个文件的形式将信任存储库上载到 Amazon S3 存储桶
<a name="w2aac19c17b9b9c13"></a>

**Example certificates.pem**  

```
-----BEGIN CERTIFICATE-----
<Certificate contents>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<Certificate contents>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<Certificate contents>
-----END CERTIFICATE-----
...
```

使用以下 [cp](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html) AWS CLI 命令将 `certificates.pem` 上传到 Amazon S3 存储桶：

```
aws s3 cp certificates.pem s3://bucket-name
```

## 为自定义域名配置双向 TLS
<a name="http-api-mutual-tls-configure"></a>

要为 HTTP API 配置双向 TLS，必须为 API 使用区域自定义域名，且 TLS 最低版本为 1.2。要了解有关创建和配置自定义域名的更多信息，请参阅 [在 API Gateway 中设置区域自定义域名](apigateway-regional-api-custom-domain-create.md)。

**注意**  
私有 API 不支持双向 TLS。

将信任存储库上传到 Amazon S3 后，您可以将自定义域名配置为使用双向 TLS。使用以下 [create-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-domain-name.html) 命令创建带有双向 TLS 的自定义域名：

```
aws apigatewayv2 create-domain-name \
    --domain-name api.example.com \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --mutual-tls-authentication TruststoreUri=s3://bucket-name/key-name
```

创建域名后，您必须为 API 操作配置 DNS 记录和基本路径映射。要了解更多信息，请参阅[在 API Gateway 中设置区域自定义域名](apigateway-regional-api-custom-domain-create.md)。

## 使用需要双向 TLS 的自定义域名调用 API
<a name="http-api-mutual-tls-invoke"></a>

要调用启用了双向 TLS 的 API，客户端必须在 API 请求中提供受信任证书。当客户端尝试调用您的 API 时，API Gateway 会在您的信任存储库中查找客户端证书的发布者。为使 API Gateway 继续处理请求，证书的发布者和直至根 CA 证书的完整信任链必须位于您的信任存储库中。

以下示例 `curl` 命令将请求发送到在请求中包含 `api.example.com,` 的 `my-cert.pem`。`my-key.key` 是证书的私有密钥。

```
curl -v --key ./my-key.key --cert ./my-cert.pem api.example.com
```

仅当您的信任存储库信任证书时，才会调用您的 API。以下情况将导致 API Gateway 使 TLS 握手失败，并以 `403` 状态代码拒绝请求。如果您的证书：
+ 不可信
+ 已过期
+ 未使用支持的算法

**注意**  
API Gateway 不验证证书是否已被吊销。

## 更新您的信任存储库
<a name="http-api-mutual-tls-update-truststore"></a>

要更新信任存储库中的证书，请将新的证书服务包上载到 Amazon S3。然后，您可以更新自定义域名以使用更新后的证书。

使用 [Amazon S3 版本控制](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html)来维护信任存储库的多个版本。当您更新自定义域名以使用新的信任存储库版本时，如果证书无效，则 API Gateway 返回警告。

API Gateway 仅在您更新域名时才生成证书警告。如果先前上传的证书过期，API Gateway 不会通知您。

使用以下 [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) 命令更新自定义域名，使其使用新的信任存储库版本：

```
aws apigatewayv2 update-domain-name \
    --domain-name api.example.com \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --mutual-tls-authentication TruststoreVersion='abcdef123'
```

## 禁用双向 TLS
<a name="http-api-mutual-tls-disable"></a>

要为自定义域名禁用双向 TLS，请从自定义域名中删除信任存储库，如以下命令所示。

以下 [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) 命令更新自定义域名，使其从自定义域名中删除信任存储库：

```
aws apigatewayv2 update-domain-name \
    --domain-name api.example.com \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --mutual-tls-authentication TruststoreUri=''
```

## HTTP API 的双向 TLS 故障排除
<a name="http-api-mutual-tls-troubleshooting"></a>

以下内容为您在启用双向 TLS 时可能遇到的错误和问题提供故障排除建议。

### 排查证书警告问题
<a name="http-api-mutual-tls-troubleshooting-certificate"></a>

 当使用双向 TLS 创建自定义域名时，如果信任存储库中的证书无效，则 API Gateway 会返回警告。在更新自定义域名以使用新的信任存储库时，也可能会出现这种情况。警告指示证书存在问题以及生成警告的证书的主题。仍然为您的 API 启用双向 TLS，但某些客户端可能无法访问您的 API。

要标识生成警告的证书，您需要解码信任存储库中的证书。您可以使用诸如 `openssl` 等工具对证书进行解码和标识其主题。

以下命令显示证书的内容，包括其主题：

```
openssl x509 -in certificate.crt -text -noout
```

更新或删除生成警告的证书，然后将新信任存储库上传到 Amazon S3。上载新的信任存储库后，请更新您的自定义域名以使用新的信任存储库。

### 域名冲突故障排除
<a name="w2aac19c17b9c19b7"></a>

错误 `"The certificate subject <certSubject> conflicts with an existing certificate from a different issuer."` 表示多个证书颁发机构已发布此域的证书。对于证书中的每个主题，双向 TLS 域的 API Gateway 中只能有一个发布者。您需要通过单个发布者获取该主题的所有证书。如果您无法控制的证书出现问题，但您可以证明域名的所有权，请[联系 支持](https://console.aws.amazon.com/support/cases#/create) 以提出支持请求。

### 域名状态消息故障排除
<a name="w2aac19c17b9c19b9"></a>

`PENDING_CERTIFICATE_REIMPORT`：这意味着您将证书重新导入到 ACM，并且验证失败，因为新证书具有 SAN（主题备用名称），而 `ownershipVerificationCertificate` 不涵盖该 SAN，或是证书中的主题或 SAN 不涵盖域名。某些内容可能配置不正确，或导入了无效的证书。您需要将有效证书重新导入 ACM。有关验证的更多信息，请参阅[验证域名所有权](https://docs.aws.amazon.com/acm/latest/userguide/domain-ownership-validation.html)。

`PENDING_OWNERSHIP_VERIFICATION`：这意味着您之前验证的证书已过期，ACM 无法自动续订。您需要续订证书或请求新证书。有关证书续订的更多信息，请查看 [ACM 对托管式证书续订进行故障排除](https://docs.aws.amazon.com/acm/latest/userguide/troubleshooting-renewal.html)指南。

# 监控 API Gateway 中的 HTTP API
<a name="http-api-monitor"></a>

您可以使用 CloudWatch 指标和 CloudWatch Logs 来监控 HTTP API。通过合并日志和指标，您可以记录错误并监控 API 的性能。

**注意**  
在以下情况下，API Gateway 可能无法生成日志和指标：  
“413 请求实体过大”错误
过多的“429 请求太多”错误
发送到没有 API 映射的自定义域的请求中出现 400 系列错误
由内部故障造成的 500 系列错误

**Topics**
+ [监控 API Gateway 中的 HTTP API 的指标](http-api-metrics.md)
+ [为 API Gateway 中的 HTTP API 配置日志记录](http-api-logging.md)

# 监控 API Gateway 中的 HTTP API 的指标
<a name="http-api-metrics"></a>

您可以使用 CloudWatch 监控 API 执行，这将从 API Gateway 收集原始数据，并将数据处理为便于阅读的近乎实时的指标。这些统计数据会保存 15 个月，从而使您能够访问历史信息，并能够更好地了解您的 Web 应用程序或服务的执行情况。默认情况下，API Gateway 指标数据会在一分钟时段内自动发送到 CloudWatch。要监控您的指标，请为您的 API 创建 CloudWatch 控制面板。有关如何创建 CloudWatch 控制面板的更多信息，请参阅《Amazon CloudWatch 用户指南》**中的[创建 CloudWatch 控制面板](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create_dashboard.html)。有关更多信息，请参阅 *Amazon CloudWatch 用户指南* 中的[什么是 Amazon CloudWatch？](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html)

HTTP API 支持以下指标。您还可以启用详细指标，以便将路由级指标写入到 Amazon CloudWatch。


| 指标 | 说明 | 
| --- | --- | 
| 4xx | 在给定期间捕获的客户端错误数。 | 
| 5xx | 在给定期间捕获的服务器端错误数。 | 
| 计数 | 给定期间内的 API 请求总数。 | 
| IntegrationLatency | 从 API Gateway 将请求中继到后端到其从后端收到响应所经过的时间。 | 
| 延迟 | 从 API Gateway 从客户端收到请求到其将响应返回给客户端所经过的时间。延迟包括集成延迟和其他 API Gateway 开销。 | 
| DataProcessed | 处理的数据量（以字节为单位）。 | 

您可以使用下表中的维度筛选 API Gateway 指标。


| 维度 | 说明 | 
| --- | --- | 
| ApiId | 筛选具有指定 API ID 的 API 的 API Gateway 指标。 | 
| ApiId、阶段 | 针对具有指定 API ID 和阶段 ID 的 API 阶段筛选 API Gateway 指标。 | 
| ApiId、方法、资源、阶段 |  使用指定的 API ID、阶段 ID、资源路径和路由 ID 筛选 API 方法的 API Gateway 指标。 除非您明确启用了详细的 CloudWatch 指标，否则 API Gateway 不会发送这些指标。要执行此操作，您可以通过调用 API Gateway V2 REST API 的 [UpdateStage](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-stages-stagename.html) 操作，将 `detailedMetricsEnabled` 属性更新为 `true`。或者，您也可以调用 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) AWS CLI 命令，以将 `DetailedMetricsEnabled` 属性更新为 `true`。启用这些指标会对您的账户额外计费。有关定价信息，请参阅 [Amazon CloudWatch 定价](https://aws.amazon.com/cloudwatch/pricing/)。  | 

# 为 API Gateway 中的 HTTP API 配置日志记录
<a name="http-api-logging"></a>

您可以开启日志记录以将日志写入 CloudWatch Logs。您可以使用[日志记录变量](http-api-logging-variables.md)来自定义日志的内容。

为了改善安全状况，我们建议您将 HTTP API 的所有阶段的日志写入 CloudWatch Logs。为遵守各种合规性框架，您可能需要执行此操作。有关更多信息，请参阅《AWS Security Hub User Guide》**中的 [Amazon API Gateway Controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html)。

要为 HTTP API 开启日志记录，您必须执行以下操作。

1. 确保您的用户具有激活日志记录所需的权限。

1. 创建 CloudWatch Logs 日志组。

1. 为 API 的某个阶段提供 CloudWatch Logs 日志组的 ARN。

## 激活日志记录的权限
<a name="http-api-logging.permissions"></a>

要开启 API 的日志记录，您的用户必须具有以下权限。

**Example**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:GetLogEvents",
                "logs:FilterLogEvents"
            ],
            "Resource": "arn:aws:logs:us-east-2:123456789012:log-group:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogDelivery",
                "logs:PutResourcePolicy",
                "logs:UpdateLogDelivery",
                "logs:DeleteLogDelivery",
                "logs:CreateLogGroup",
                "logs:DescribeResourcePolicies",
                "logs:GetLogDelivery",
                "logs:ListLogDeliveries"
            ],
            "Resource": "*"
        }
    ]
}
```

## 创建日志组并激活 HTTP API 的日志记录
<a name="http-api-enable-logging"></a>

您可以使用 AWS 管理控制台 或 AWS CLI 创建日志组并激活访问日志记录。

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

1.  创建日志组。

   要了解如何使用控制台建立日志组，请参阅[《Amazon CloudWatch Logs 用户指南》中的“创建日志组”](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html)。

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

1. 选择 HTTP API。

1. 在主导航面板的 **Monitor**（监控）选项卡下，选择 **Logging**（日志记录）。

1. 选择要激活日志记录的阶段，然后选择 **Select**（选择）。

1. 选择 **Edit**（编辑）以激活访问日志。

1. 开启 **Access logging**（访问日志），进入 CloudWatch Logs，然后选择日志格式。

1. 选择**保存**。

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

以下 [create-log-group](https://docs.aws.amazon.com/cli/latest/reference/logs/create-log-group.html) 命令创建日志组：

```
aws logs create-log-group --log-group-name my-log-group
```

您需要日志组的 Amazon 资源名称（ARN）才能开启日志记录。ARN 格式为 arn:aws:logs:*region*:*account-id*:log-group:*log-group-name*。

以下 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) 命令为 HTTP API 的 `$default` 阶段开启日志记录：

```
aws apigatewayv2 update-stage --api-id abcdef \
    --stage-name '$default' \
    --access-log-settings '{"DestinationArn": "arn:aws:logs:region:account-id:log-group:log-group-name", "Format": "$context.identity.sourceIp - - [$context.requestTime] \"$context.httpMethod $context.routeKey $context.protocol\" $context.status $context.responseLength $context.requestId"}'
```

------

## 日志格式示例
<a name="http-api-enable-logging.examples"></a>

一些常用的访问日志格式的示例在 API Gateway 控制台中显示，下面列出了这些格式。
+ `CLF` ([常用日志格式](https://httpd.apache.org/docs/current/logs.html#common) )：

  ```
  $context.identity.sourceIp - - [$context.requestTime] "$context.httpMethod $context.routeKey $context.protocol" $context.status $context.responseLength $context.requestId $context.extendedRequestId
  ```
+  `JSON`: 

  ```
  { "requestId":"$context.requestId", "ip": "$context.identity.sourceIp", "requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod","routeKey":"$context.routeKey", "status":"$context.status","protocol":"$context.protocol", "responseLength":"$context.responseLength", "extendedRequestId": "$context.extendedRequestId" }
  ```
+ `XML`: 

  ```
  <request id="$context.requestId"> <ip>$context.identity.sourceIp</ip> <requestTime>$context.requestTime</requestTime> <httpMethod>$context.httpMethod</httpMethod> <routeKey>$context.routeKey</routeKey> <status>$context.status</status> <protocol>$context.protocol</protocol> <responseLength>$context.responseLength</responseLength> <extendedRequestId>$context.extendedRequestId</extendedRequestId> </request>
  ```
+ `CSV`（逗号分隔值）：

  ```
  $context.identity.sourceIp,$context.requestTime,$context.httpMethod,$context.routeKey,$context.protocol,$context.status,$context.responseLength,$context.requestId,$context.extendedRequestId
  ```

# 自定义 HTTP API 访问日志
<a name="http-api-logging-variables"></a>

您可以使用以下变量自定义 HTTP API 访问日志。要了解有关 HTTP API 的访问日志的更多信息，请参阅 [为 API Gateway 中的 HTTP API 配置日志记录](http-api-logging.md)。


| 参数 | 说明 | 
| --- | --- | 
| \$1context.accountId |  API 拥有者的 AWS 账户 ID。  | 
| \$1context.apiId |  API Gateway 分配给您的 API 的标识符。  | 
| \$1context.authorizer.claims.property |  成功对方法调用方进行身份验证后从 JSON Web 令牌（JWT）返回的声明的属性，如 `$context.authorizer.claims.username`。有关更多信息，请参阅 [在 API Gateway 中使用 JWT 授权方控制对 HTTP API 的访问](http-api-jwt-authorizer.md)。  调用 `$context.authorizer.claims` 将返回 null。   | 
| \$1context.authorizer.error | 从授权方返回的错误消息。 | 
| \$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`。  | 
| \$1context.awsEndpointRequestId |  `x-amz-request-id` 或 `x-amzn-requestId` 标头中AWS端点的请求 ID。  | 
| \$1context.awsEndpointRequestId2 |  来自 `x-amz-id-2` 标头的AWS端点的请求 ID。  | 
| \$1context.customDomain.basePathMatched |  传入请求所匹配的 API 映射路径。适用于客户端使用自定义域名访问 API 的情况。例如，如果客户端向 `https://api.example.com/v1/orders/1234` 发送请求，且该请求匹配路径为 `v1/orders` 的 API 映射，则值为 `v1/orders`。要了解更多信息，请参阅“[将 API 阶段映射到 HTTP API 的自定义域名](http-api-mappings.md)”。  | 
| \$1context.dataProcessed | 处理的数据量（以字节为单位）。 | 
| \$1context.domainName |  用于调用 API 的完整域名。这应与传入的 `Host` 标头相同。  | 
| \$1context.domainPrefix |  `$context.domainName` 的第一个标签。  | 
| \$1context.error.message |  包含 API Gateway 错误消息的字符串。  | 
| \$1context.error.messageString | \$1context.error.message 的带引号的值，即 "\$1context.error.message"。 | 
| \$1context.error.responseType |  一种 `GatewayResponse` 类型。有关更多信息，请参阅 [使用 CloudWatch 指标监控 WebSocket API 执行](apigateway-websocket-api-logging.md) 和 [设置网关响应以自定义错误响应](api-gateway-gatewayResponse-definition.md#customize-gateway-responses)。  | 
| \$1context.extendedRequestId | 等效于 \$1context.requestId。 | 
| \$1context.httpMethod |  所用的 HTTP 方法。有效值包括：`DELETE`、`GET`、`HEAD`、`OPTIONS`、`PATCH`、`POST` 和 `PUT`。  | 
| \$1context.identity.accountId |  与请求关联的 AWS 账户 ID。对于使用 IAM 授权的路由支持此项。  | 
| \$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)。对于使用 IAM 授权的路由支持此项。  | 
| \$1context.identity.clientCert.clientCertPem |  客户端在双向 TLS 身份验证过程中提供的 PEM 编码的客户端证书。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。  | 
| \$1context.identity.clientCert.subjectDN |  客户端提供的证书的主题的可分辨名称。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。  | 
| \$1context.identity.clientCert.issuerDN |  客户端提供的证书的颁发者的可分辨名称。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。  | 
| \$1context.identity.clientCert.serialNumber |  证书的序列号。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。  | 
| \$1context.identity.clientCert.validity.notBefore |  证书无效之前的日期。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。  | 
| \$1context.identity.clientCert.validity.notAfter |  证书无效后的日期。当客户端使用已启用双向 TLS 的自定义域名访问 API 时提供。  | 
| \$1context.identity.sourceIp |  向 API Gateway 端点发出请求的即时 TCP 连接的源 IP 地址。  | 
| \$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)。对于使用 IAM 授权的路由支持此项。有关更多信息，请参阅 [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)。  | 
| \$1context.integration.error | 从集成返回的错误消息。等效于 \$1context.integrationErrorMessage。 | 
| \$1context.integration.integrationStatus | 对于 Lambda 代理集成，从 AWS Lambda（而不是从后端 Lambda 函数代码）返回的状态代码。 | 
| \$1context.integration.latency | 集成延迟（毫秒）。等效于 \$1context.integrationLatency。 | 
| \$1context.integration.requestId | AWS 端点的请求 ID。等效于 \$1context.awsEndpointRequestId。 | 
| \$1context.integration.status | 从集成返回的状态代码。对于 Lambda 代理集成，这是 Lambda 函数代码返回的状态代码。 | 
| \$1context.integrationErrorMessage |  包含集成错误消息的字符串。  | 
| \$1context.integrationLatency | 集成延迟（毫秒）。 | 
| \$1context.integrationStatus | 对于 Lambda 代理集成，此参数表示从 AWS Lambda（而不是从后端 Lambda 函数）返回的状态代码。 | 
| \$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 |  API Gateway 分配给 API 请求的 ID。  | 
| \$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.responseLatency | 响应延迟（毫秒）。 | 
| \$1context.responseLength | 响应负载长度（以字节为单位）。 | 
| \$1context.routeKey |  API 请求的路由密钥，例如 `/pets`。  | 
| \$1context.stage |  API 请求的部署阶段（例如，`beta` 或 `prod`）。  | 
| \$1context.status | 方法响应状态。 | 

# 排查 API Gateway 中 HTTP API 的问题
<a name="http-api-troubleshooting"></a>

以下主题为您在使用 HTTP API 时可能遇到的错误和问题提供问题排查建议。

**Topics**
+ [对 HTTP API Lambda 集成的问题进行故障排查](http-api-troubleshooting-lambda.md)
+ [排查 HTTP API JWT 授权方的问题](http-api-troubleshooting-jwt.md)

# 对 HTTP API Lambda 集成的问题进行故障排查
<a name="http-api-troubleshooting-lambda"></a>

以下内容为您在将 [AWS Lambda 集成](http-api-develop-integrations-lambda.md) 与 HTTP API 结合使用时可能遇到的错误和问题提供故障排除建议。

## 问题：我的 API 与 Lambda 集成返回 `{"message":"Internal Server Error"}`
<a name="http-api-troubleshooting-lambda-internal-server-error"></a>

要解决此内部服务器错误，请将`$context.integrationErrorMessage`[日志记录变量](http-api-logging-variables.md)添加到日志格式中，然后查看 HTTP API 的日志。为此，请执行以下操作：

**要使用 创建日志组AWS 管理控制台**

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

1. 选择**日志组**。

1. 选择**创建日志组**。

1. 输入日志组名称，然后选择**创建**。

1. 记下您的日志组的 Amazon 资源名称 (ARN)。ARN 格式为 arn:aws:logs:*region*: *account-id*:log-group:*log-group-name*。您需要日志组 ARN 才能为 HTTP API 启用访问日志记录。

**添加 `$context.integrationErrorMessage` 日志记录变量**

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

1. 选择您的 HTTP API。

1. 在**监控**下，选择**日志记录**。

1. 选择 API 的一个阶段。

1. 选择**编辑**，然后启用访问日志记录。

1. 为**日志目标**输入您在上一步中创建的安全组的 ARN。

1. 对于**日志格式**，选择 **CLF**。API Gateway 创建一个示例日志格式。

1. 将 `$context.integrationErrorMessage` 添加到日志格式的末尾。

1. 选择**保存**。

**查看 API 的日志**

1. 生成日志。使用浏览器或 `curl` 调用您的 API。

   ```
   $curl https://api-id.execute-api.us-west-2.amazonaws.com/route
   ```

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

1. 选择您的 HTTP API。

1. 在**监控**下，选择**日志记录**。

1. 选择您启用了日志记录的 API 阶段。

1. 选择**查看 CloudWatch 中的日志**。

1. 选择最新的日志流以查看 HTTP API 的日志。

1. 您的日志条目应类似于以下内容：  
![\[CloudWatch Logs 日志条目，显示来自 Lambda 的集成错误消息。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/troubleshoot-http-api-logs.png)

因为我们已将 `$context.integrationErrorMessage` 添加到日志格式，所以我们在日志中会看到一条总结此问题的错误消息。

您的日志可能包含不同的错误消息，以指示您的 Lambda 函数代码存在问题。在这种情况下，检查您的 Lambda 函数代码，并验证您的 Lambda 函数以[所需格式](http-api-develop-integrations-lambda.md#http-api-develop-integrations-lambda.response)返回响应。如果您的日志不包含错误消息，请在日志格式中添加 `$context.error.message` 和 `$context.error.responseType` 以获取更多信息以帮助进行故障排除。

在这种情况下，日志显示 API Gateway 不具备调用 Lambda 函数所需的权限。

当您在 API Gateway 控制台中创建 Lambda 集成时，API Gateway 会自动配置权限以调用 Lambda 函数。当您使用 AWS CLI、CloudFormation 或开发工具包创建 Lambda 集成时，您必须授予 API Gateway 调用函数的权限。以下 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令向不同的 HTTP API 路由授予调用 Lambda 函数的权限。

**Example 示例 – 针对 HTTP API 的 `$default` 阶段和 `$default` 路由**  

```
aws lambda add-permission \
    --function-name my-function \
    --statement-id apigateway-invoke-permissions \
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/\$default/\$default"
```

**Example 示例 – 针对 HTTP API 的 `prod` 阶段和 `test` 路由**  

```
aws lambda add-permission \
    --function-name my-function \
    --statement-id apigateway-invoke-permissions \
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/prod/*/test"
```

在 Lambda 控制台的**权限**选项卡中[确认函数策略](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)。

尝试再次调用您的 API。您应该看到 Lambda 函数的响应。

# 排查 HTTP API JWT 授权方的问题
<a name="http-api-troubleshooting-jwt"></a>

以下内容为您在将 JSON Web 令牌 (JWT) 授权方与 HTTP API 结合使用时可能遇到的错误和问题提供故障排除建议。

## 问题：我的 API 返回 `401 {"message":"Unauthorized"}`
<a name="http-api-troubleshooting-jwt.unauthorized"></a>

检查来自 API 的响应中的 `www-authenticate` 标头。

以下命令使用 `curl` 将请求发送到具有 JWT 授权方（ `$request.header.Authorization` 作为其身份源）的 API。

```
$curl -v -H "Authorization: token" https://api-id.execute-api.us-west-2.amazonaws.com/route
```

来自 API 的响应包含一个 `www-authenticate` 标头。

```
...
< HTTP/1.1 401 Unauthorized
< Date: Wed, 13 May 2020 04:07:30 GMT
< Content-Length: 26
< Connection: keep-alive
< www-authenticate: Bearer scope="" error="invalid_token" error_description="the token does not have a valid audience"
< apigw-requestid: Mc7UVioPPHcEKPA=
<
* Connection #0 to host api-id.execute-api.us-west-2.amazonaws.com left intact
{"message":"Unauthorized"}}
```

在这种情况下，`www-authenticate` 标头显示未为有效的受众颁发令牌。为使 Lambda 对请求授权，JWT 的 `aud` 或 `client_id` 声明必须与为授权方配置的受众条目之一匹配。API Gateway 只有在 `aud` 不存在时才验证 `client_id`。当 `aud` 和 `client_id` 同时存在时，API Gateway 会评估 `aud`。

您还可以对 JWT 进行解码，并验证它与 API 所需的发布者、受众和作用域匹配。网站 [jwt.io](https://jwt.io/) 可以在浏览器中调试 JWT。OpenID Foundation 维护[用于处理 JWT 的库列表](https://openid.net/developers/jwt-jws-jwe-jwk-and-jwa-implementations/)。

要了解有关 JWT 授权方的更多信息，请参阅 [在 API Gateway 中使用 JWT 授权方控制对 HTTP API 的访问](http-api-jwt-authorizer.md)。