

# 开发 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. 选择**下载**。