将 AWS Lambda 与 Amazon API Gateway 结合使用 - AWS Lambda

将 AWS Lambda 与 Amazon API Gateway 结合使用

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

向 Lambda 函数添加公有终端节点

  1. 打开 Lambda 控制台的“函数”页面

  2. 选择函数。

  3. Designer 下方,选择 Add trigger (添加触发器)

  4. 选择 API Gateway (API 网关)

  5. 对于 API,请选择 Create an API (创建 API)

  6. 对于 Security (安全性),请选择 Open (打开)

  7. 选择 Add

在设计器中选择 API Gateway (API 网关) 触发器后,选择要使用 API 网关 调用函数的终端节点。


      附加到 Lambda 函数的 API 网关 API 终端节点。

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

API 路径格式

  • /prod/prod 阶段和根资源。

  • /prod/userprod 阶段和 user 资源。

  • /dev/{proxy+}dev 阶段中的任何路线。

  • / – (HTTP API) 默认阶段和根资源。

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

Amazon API Gateway 会使用包含 HTTP 请求的 JSON 表示形式的事件同步调用您的函数。对于自定义集成,该事件为请求的正文。对于代理集成,该事件具有已确定的结构。以下示例显示了来自 API 网关 REST API 的代理事件。

event.json API 网关 代理事件 (REST API)

{ "resource": "/", "path": "/", "httpMethod": "GET", "requestContext": { "resourcePath": "/", "httpMethod": "GET", "path": "/Prod/", ... }, "headers": { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "accept-encoding": "gzip, deflate, br", "Host": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", "X-Amzn-Trace-Id": "Root=1-5e66d96f-7491f09xmpl79d18acf3d050", ... }, "multiValueHeaders": { "accept": [ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" ], "accept-encoding": [ "gzip, deflate, br" ], ... }, "queryStringParameters": null, "multiValueQueryStringParameters": null, "pathParameters": null, "stageVariables": null, "body": null, "isBase64Encoded": false }

此示例显示了用于获取 REST API Prod 阶段根路径的 GET 请求所对应的事件。事件形状和内容因 API 类型 和配置而异。

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

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

index.js – 代理集成响应对象 (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 响应,然后再将其发送到发出原始请求的客户端。

例 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 }

API 中的资源会定义一个或多个方法,如 GET 或 POST。方法具有将请求传送给 Lambda 函数或其他集成类型的集成。您可以单独定义每个资源和方法,也可以使用特定的资源和方法类型来匹配属于特定模式的所有请求。代理资源会捕获某个资源下的所有路径。ANY 方法会捕获所有 HTTP 方法。

权限

Amazon API Gateway 将从函数的基于资源的策略获取调用函数的权限。您可以授予对整个 API 的调用权限,也可以仅授予对某个阶段、资源或方法的有限访问权限。

当您使用 Lambda 控制台、API 网关 控制台或 AWS SAM 模板向函数添加 API 时,会自动更新函数的基于资源的策略。以下示例显示了一个函数策略,其中包含通过 AWS SAM 模板添加的语句。

例 函数策略

{ "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:lambda:us-east-2:123456789012:function:nodejs-apig-function-1G3MXMPLXVXYI", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:execute-api:us-east-2:123456789012:ktyvxmpls1/*/GET/" } } } ] }

在 Lambda 控制台的 Permissions (权限) 选项卡中确认函数策略

您可以通过以下 API 操作手动管理函数策略权限:

使用 add-permission 命令,可授予对现有 API 的调用权限。

$ aws lambda add-permission --function-name my-function \ --statement-id apigateway-get --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:us-east-2:123456789012:mnh1xmpli7/default/GET/" { "Statement": "{\"Sid\":\"apigateway-test-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:my-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1xmpli7/default/GET\"}}}" }
注意

如果您的函数和 API 位于不同的区域,则源 ARN 中的区域标识符必须与函数的区域(而不是 API 的区域)匹配。当 API 网关 调用函数时,它会使用基于 API 的 ARN 的资源 ARN,但该资源 ARN 已被修改为与函数的区域相匹配。

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

资源模式

  • mnh1xmpli7/*/GET/* – 对所有阶段中的所有资源调用 GET 方法。

  • mnh1xmpli7/prod/ANY/user – 对 prod 阶段中的 user 资源调用 ANY 方法。

  • mnh1xmpli7/*/*/* – 对所有阶段中的所有资源调用 ANY 方法。

有关查看策略和删除语句的详细信息,请参阅清除基于资源的策略

利用 API 网关 API 处理错误

API 网关 将所有调用和函数错误视为内部错误。如果 Lambda API 拒绝调用请求,则 API 网关 返回 500 错误代码。如果函数运行但返回错误,或返回格式错误的响应,则 API 网关 返回 502。在这两种情况下,来自 API 网关 的响应的正文都是 {"message": "Internal server error"}

以下示例显示导致 API 网关 中出现函数错误和 502 的请求的 X-Ray 跟踪映射。客户端收到通用错误消息。


        使用 API 网关 跟踪函数错误的映射。

要自定义错误响应,您必须捕获代码中的错误并以所需格式设置响应的格式。

index.js – 错误格式设置

var formatError = function(error){ var response = { "statusCode": error.statusCode, "headers": { "Content-Type": "text/plain", "x-amzn-ErrorType": error.code }, "isBase64Encoded": false, "body": error.code + ": " + error.message } return response }

API 网关 将此响应转换为带有自定义状态代码和正文的 HTTP 错误。在跟踪映射中,函数节点为绿色,因为它处理了错误。


        使用 API 网关 跟踪格式化错误的映射。

选择 API 类型

API 网关 支持三种可调用 Lambda 函数的 API:

  • HTTP API – 一种轻型的低延迟 RESTful API。

  • REST API – 一种功能丰富的可定制 RESTful API。

  • WebSocket API – 一种 Web API,可与客户端保持持久连接并进行全双工通信。

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

HTTP API 功能

  • 自动部署 – 当您修改路线或集成时,更改会自动部署到启用了自动部署的阶段。

  • 默认阶段 – 您可以创建默认阶段 ($default),以便在 API URL 的根路径处提供请求。对于具名阶段,必须在路径的开头包含阶段名称。

  • CORS 配置 – 您可以配置 API,使其将 CORS 标头添加到传出响应中,而不是在函数代码中手动添加。

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

REST API 功能

  • 集成类型 – REST API 支持自定义 Lambda 集成。使用自定义集成,您可以直接将请求正文发送到函数,也可以对其应用转换模板,然后再发送到函数。

  • 访问控制 – REST API 支持更多身份验证和授权选项。

  • 监控和跟踪 – REST API 支持 AWS X-Ray 跟踪和其他日志记录选项。

要查看详细的比较,请参阅 API 网关 开发人员指南中的在 HTTP API 和 REST API 之间选择

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

HTTP API 支持简化的事件格式(2.0 版)。以下示例显示了来自 HTTP API 的事件。

event-v2.json – API 网关 代理事件 (HTTP API)

{ "version": "2.0", "routeKey": "ANY /nodejs-apig-function-1G3XMPLZXVXYI", "rawPath": "/default/nodejs-apig-function-1G3XMPLZXVXYI", "rawQueryString": "", "cookies": [ "s_fid=7AABXMPL1AFD9BBF-0643XMPL09956DE2", "regStatus=pre-register" ], "headers": { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "accept-encoding": "gzip, deflate, br", ... }, "requestContext": { "accountId": "123456789012", "apiId": "r3pmxmplak", "domainName": "r3pmxmplak.execute-api.us-east-2.amazonaws.com", "domainPrefix": "r3pmxmplak", "http": { "method": "GET", "path": "/default/nodejs-apig-function-1G3XMPLZXVXYI", "protocol": "HTTP/1.1", "sourceIp": "205.255.255.176", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36" }, "requestId": "JKJaXmPLvHcESHA=", "routeKey": "ANY /nodejs-apig-function-1G3XMPLZXVXYI", "stage": "default", "time": "10/Mar/2020:05:16:23 +0000", "timeEpoch": 1583817383220 }, "isBase64Encoded": true }

有关更多信息,请参阅《API 网关 开发人员指南》中的 AWS Lambda 集成

示例应用程序

本指南的 GitHub 存储库中提供了 API 网关的以下示例应用程序。

  • 带有 Node.js 的 API Gateway – 具有 AWS SAM 模板的函数,该模板可用于创建启用了 AWS X-Ray 跟踪的 REST API。它包含用于部署和调用函数、测试 API 以及执行清理的脚本。

Lambda 还提供了蓝图模板,您可以使用这些蓝图和模板在 Lambda 控制台中创建 API Gateway 应用程序。