

# 使用 Amazon API Gateway 端点调用 Lambda 函数
<a name="services-apigateway"></a>

您可以使用 Amazon API Gateway 为 Lambda 函数创建带有 HTTP 端点的 Web API。API Gateway 提供工具，用于创建和记录向 Lambda 函数路由 HTTP 请求的 Web API。您可以使用身份验证和授权控制来保护对 API 的访问。您的 API 可以通过互联网传输流量，也可以仅允许在您的 VPC 内访问。

**提示**  
Lambda 提供了两种方法来通过 HTTP 端点调用函数：API Gateway 和 Lambda 函数 URL。如果您不确定哪种方法最适合您的应用场景，请参阅[选择使用 HTTP 请求调用 Lambda 函数的方法](apig-http-invoke-decision.md)。

API 中的资源会定义一个或多个方法，如 GET 或 POST。方法具有将请求传送给 Lambda 函数或其他集成类型的集成。您可以单独定义每个资源和方法，也可以使用特定的资源和方法类型来匹配属于特定模式的所有请求。[代理资源](https://docs.amazonaws.cn/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html)会捕获某个资源下的所有路径。`ANY` 方法会捕获所有 HTTP 方法。

**Topics**
+ [选择 API 类型](#services-apigateway-apitypes)
+ [向 Lambda 函数添加终端节点](#apigateway-add)
+ [代理集成](#apigateway-proxy)
+ [事件格式](#apigateway-example-event)
+ [响应格式](#apigateway-types-transforms)
+ [权限](#apigateway-permissions)
+ [示例应用程序](#services-apigateway-samples)
+ [Powertools for Amazon Lambda 中的事件处理程序](#services-apigateway-powertools)
+ [教程：利用 API Gateway 使用 Lambda](services-apigateway-tutorial.md)
+ [利用 API Gateway API 处理 Lambda 错误](services-apigateway-errors.md)
+ [选择使用 HTTP 请求调用 Lambda 函数的方法](apig-http-invoke-decision.md)

## 选择 API 类型
<a name="services-apigateway-apitypes"></a>

API Gateway 支持三种可调用 Lambda 函数的 API 类型：
+ [HTTP API](https://docs.amazonaws.cn/apigateway/latest/developerguide/http-api.html)：一种轻型的低延迟 RESTful API。
+ [REST API](https://docs.amazonaws.cn/apigateway/latest/developerguide/apigateway-rest-api.html)：一种功能丰富的可定制 RESTful API。
+ [WebSocket API](https://docs.amazonaws.cn/apigateway/latest/developerguide/apigateway-websocket-api.html)：一种 Web API，可与客户端保持持久连接并进行全双工通信。

HTTP API 和 REST API 都是用于处理 HTTP 请求并返回响应的 RESTful API。HTTP API 后推出，是使用 API Gateway 版本 2 API 构建的。以下是 HTTP API 的新功能：

**HTTP API 功能**
+ **自动部署** – 当您修改路线或集成时，更改会自动部署到启用了自动部署的阶段。
+ **默认阶段** – 您可以创建默认阶段 (`$default`)，以便在 API URL 的根路径处提供请求。对于具名阶段，必须在路径的开头包含阶段名称。
+ **CORS 配置** – 您可以配置 API，使其将 CORS 标头添加到传出响应中，而不是在函数代码中手动添加。

REST API 是 API Gateway 自发布起就支持的典型 RESTful API。REST API 现在具有更多的自定义、集成和管理功能。

**REST API 功能**
+ **集成类型** – REST API 支持自定义 Lambda 集成。使用自定义集成，您可以直接将请求正文发送到函数，也可以对其应用转换模板，然后再发送到函数。
+ **访问控制** – REST API 支持更多身份验证和授权选项。
+ **监控和跟踪** – REST API 支持 Amazon X-Ray 跟踪和其他日志记录选项。

有关详细比较，请参阅《API Gateway 开发人员指南》**中的[在 HTTP API 和 REST API 之间选择](https://docs.amazonaws.cn/apigateway/latest/developerguide/http-api-vs-rest.html)。

WebSocket API 也使用 API Gateway 版本 2 API 并支持类似的功能集。对于受益于客户端和 API 之间的持久连接的应用程序，请使用 WebSocket API。WebSocket API 提供全双工通信，这意味着客户端和 API 都可以持续发送消息，而无需等待响应。

HTTP API 支持简化的事件格式（2.0 版）。有关来自 HTTP API 的事件的示例，请参阅[针对 API Gateway 中的 HTTP API 创建 Amazon Lambda 代理集成](https://docs.amazonaws.cn//apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)。

有关更多信息，请参阅[针对 API Gateway 中的 HTTP API 创建 Amazon Lambda 代理集成](https://docs.amazonaws.cn/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)。

## 向 Lambda 函数添加终端节点
<a name="apigateway-add"></a>

**向 Lambda 函数添加公有端点**

1. 打开 Lamba 控制台的[函数](https://console.amazonaws.cn/lambda/home#/functions)页面。

1. 选择函数。

1. 在 **Function overview**（函数概览）下，选择 **Add trigger**（添加触发器）。

1. 选择 **API Gateway (API 网关)**。

1. 选择 **Create an API**（创建 API）或 **Use an existing API**（使用现有 API）。

   1. **New API（新 API）：**对于 **API type**（API 类型），请选择 **HTTP API**。有关更多信息，请参阅 [选择 API 类型](#services-apigateway-apitypes)。

   1. **现有 API：**从下拉列表中选择 API 或输入 API ID（例如，r3pmxmplak）。

1. 对于 **Security (安全性)**，请选择 **Open (打开)**。

1. 选择**添加**。

## 代理集成
<a name="apigateway-proxy"></a>

API Gateway API 由阶段、资源、方法和集成组成。阶段和资源决定终端节点的路径：

**API 路径格式**
+ `/prod/` – `prod` 阶段和根资源。
+ `/prod/user` – `prod` 阶段和 `user` 资源。
+ `/dev/{proxy+}` – `dev` 阶段中的路线。
+ `/` – (HTTP API) 默认阶段和根资源。

Lambda 集成将路径和 HTTP 方法的组合映射到 Lambda 函数。您可以将 API Gateway 配置为按原样（自定义集成）传递 HTTP 请求体，或者将请求正文封装在包含所有请求信息（包括标头、资源、路径和方法）的文档中。

有关更多信息，请参阅 [API Gateway 中的 Lambda 代理集成](https://docs.amazonaws.cn/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html)。

## 事件格式
<a name="apigateway-example-event"></a>

Amazon API Gateway 会使用包含 HTTP 请求的 JSON 表示形式的事件[同步](invocation-sync.md)调用函数。对于自定义集成，该事件为请求的正文。对于代理集成，该事件具有已确定的结构。有关来自 API Gateway REST API 的代理事件的示例，请参阅《API Gateway 开发人员指南》**中的[用于代理集成的 Lambda 函数的输入格式](https://docs.amazonaws.cn/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format)。

## 响应格式
<a name="apigateway-types-transforms"></a>

API Gateway 会等待函数响应并将结果转发给调用方。对于自定义集成，您可以定义集成响应和方法响应，以将函数的输出转换为 HTTP 响应。对于代理集成，函数必须以特定格式的响应形式来做出响应。

以下示例显示了来自 Node.js 函数的响应对象。该响应对象表示包含 JSON 文档的成功 HTTP 响应。

**Example index.mjs：代理集成响应对象（Node.js）**  

```
var response = {
      "statusCode": 200,
      "headers": {
        "Content-Type": "application/json"
      },
      "isBase64Encoded": false,
      "multiValueHeaders": { 
        "X-Custom-Header": ["My value", "My other value"],
      },
      "body": "{\n  \"TotalCodeSize\": 104330022,\n  \"FunctionCount\": 26\n}"
    }
```

Lambda 运行时会将响应对象序列化为 JSON 并将其发送给 API。此 API 会解析该响应并用它来创建 HTTP 响应，然后再将其发送到发出原始请求的客户端。

**Example HTTP 响应**  

```
< HTTP/1.1 200 OK
  < Content-Type: application/json
  < Content-Length: 55
  < Connection: keep-alive
  < x-amzn-RequestId: 32998fea-xmpl-4268-8c72-16138d629356
  < X-Custom-Header: My value
  < X-Custom-Header: My other value
  < X-Amzn-Trace-Id: Root=1-5e6aa925-ccecxmplbae116148e52f036
  <
  {
    "TotalCodeSize": 104330022,
    "FunctionCount": 26
  }
```

## 权限
<a name="apigateway-permissions"></a>

Amazon API Gateway 将从函数的[基于资源的策略](access-control-resource-based.md)获取调用函数的权限。您可以授予对整个 API 的调用权限，也可以仅授予对某个阶段、资源或方法的有限访问权限。

当您使用 Lambda 控制台、API Gateway 控制台或 Amazon SAM 模板向函数添加 API 时，会自动更新函数的基于资源的策略。以下是一个示例函数策略。

**Example 函数策略**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Id": "default",
  "Statement": [
    {
      "Sid": "nodejs-apig-functiongetEndpointPermissionProd-BWDBXMPLXE2F",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws-cn:lambda:cn-north-1:{{111122223333}}:function:nodejs-apig-function-1G3MXMPLXVXYI",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "111122223333"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws-cn:execute-api:cn-north-1:{{111122223333}}:ktyvxmpls1/*/GET/"
        }
      }
    }
  ]
}
```

您可以通过以下 API 操作手动管理函数策略权限：
+ [AddPermission](https://docs.amazonaws.cn/lambda/latest/api/API_AddPermission.html)
+ [RemovePermission](https://docs.amazonaws.cn/lambda/latest/api/API_RemovePermission.html)
+ [GetPolicy](https://docs.amazonaws.cn/lambda/latest/api/API_GetPolicy.html)

使用 `add-permission` 命令，可授予对现有 API 的调用权限。示例：

```
aws lambda add-permission \
  --function-name my-function \
  --statement-id apigateway-get --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com.cn \
  --source-arn "arn:aws:execute-api:cn-north-1:123456789012:mnh1xmpli7/default/GET/"
```

您应看到以下输出：

```
{
    "Statement": "{\"Sid\":\"apigateway-test-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com.cn\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:cn-north-1:123456789012:function:my-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:cn-north-1:123456789012:mnh1xmpli7/default/GET\"}}}"
}
```

**注意**  
如果您的函数和 API 位于不同的 Amazon Web Services 区域，则源 ARN 中的区域标识符必须与函数的区域（而不是 API 的区域）匹配。当 API Gateway 调用函数时，它会使用基于 API ARN 的资源 ARN，但该资源 ARN 已被修改为与函数的区域相匹配。

此示例中的源 ARN 授予对 API 默认阶段根资源 GET 方法的集成的权限，其 ID为 `mnh1xmpli7`。您可以在源 ARN 中使用星号授予对多个阶段、方法或资源的权限。

**资源模式**
+ `mnh1xmpli7/*/GET/*` – 对所有阶段中的所有资源调用 GET 方法。
+ `mnh1xmpli7/prod/ANY/user` – 对 `prod` 阶段中的 `user` 资源调用 ANY 方法。
+ `mnh1xmpli7/*/*/*` – 对所有阶段中的所有资源调用 ANY 方法。

有关查看策略和删除语句的详细信息，请参阅[在 Lambda 中查看基于资源的 IAM 策略](access-control-resource-based.md)。

## 示例应用程序
<a name="services-apigateway-samples"></a>

[带有 Node.js 的 API Gateway](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/nodejs-apig) 示例应用程序包含具有 Amazon SAM 模板的函数，该模板可用于创建启用了 Amazon X-Ray 跟踪的 REST API。它还包含用于部署和调用函数、测试 API 以及执行清理的脚本。

## Powertools for Amazon Lambda 中的事件处理程序
<a name="services-apigateway-powertools"></a>

在编写由 API Gateway 端点（HTTP 或 REST）调用的 Lambda 函数时，Powertools for Amazon Lambda 工具包中的事件处理程序提供路由、中间件、CORS 配置、OpenAPI 规范生成、请求验证、错误处理和其他有用的功能。事件处理程序实用程序适用于 Python 和 TypeScript/JavaScript。有关更多信息，请参阅 *Powertools for Amazon Lambda (Python) 文档*中的[事件处理程序 REST API](https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/) 和 *Powertools for Amazon Lambda (TypeScript) 文档*中的[事件处理程序 HTTP API](https://docs.amazonaws.cn/powertools/typescript/latest/features/event-handler/http/)。

### Python
<a name="services-apigateway-powertools-python"></a>

```
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing.lambda_context import LambdaContext

app = APIGatewayRestResolver()
logger = Logger()

@app.get("/healthz")
def ping():
    return {"message": "health status ok"}

@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)  
def lambda_handler(event: dict, context: LambdaContext) -> dict:
    return app.resolve(event, context)
```

### Typescript
<a name="services-apigateway-powertools-typescript"></a>

```
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import { Logger } from '@aws-lambda-powertools/logger';
import {
  correlationPaths,
  search,
} from '@aws-lambda-powertools/logger/correlationId';
import type { Context } from 'aws-lambda/handler';

const logger = new Logger({
  correlationIdSearchFn: search,
});

const app = new Router({ logger });

app.get("/healthz", async () => {
  return { message: "health status ok" };
});

export const handler = async (event: unknown, context: Context) => {
  // You can continue using other utilities just as before
  logger.addContext(context);
  logger.setCorrelationId(event, correlationPaths.API_GATEWAY_REST);
  return app.resolve(event, context);
};
```