教程:通过两种 AWS 服务集成和一种 Lambda 非代理集成创建计算器 REST API - Amazon API Gateway

教程:通过两种 AWS 服务集成和一种 Lambda 非代理集成创建计算器 REST API

非代理集成教程入门完全使用 Lambda Function 集成。Lambda Function 集成是 AWS Service 集成类型的特殊情况,该类型可为您执行大量集成设置,如自动添加所需的基于资源的权限以调用 Lambda 函数。在这里,三个集成中的两个集成使用的是 AWS Service 集成。在此集成类型中,您将具有更多控制,但您将需要手动执行任务,如创建和指定包含相应权限的 IAM 角色。

在本教程中,您将创建一个 Calc Lambda 函数,该函数可实施基本算术运算,同时接受 JSON 格式的输入和输出。然后,您将采用以下方式创建一个 REST API 并将其与 Lambda 函数集成:

  1. 通过在 GET 资源上公开 /calc 方法以调用 Lambda 函数,同时提供输入作为查询字符串参数。(AWS Service 集成)

  2. 通过在 POST 资源上公开 /calc 方法以调用 Lambda 函数,同时在方法请求负载中提供输入。(AWS Service 集成)

  3. 通过在嵌套的 GET 资源上公开 /calc/{operand1}/{operand2}/{operator} 以调用 Lambda 函数,同时提供输入作为路径参数。(Lambda Function 集成)

除了尝试使用本教程外,您可能还希望研究 Calc API 的 OpenAPI 定义文件,您可通过按照 使用 OpenAPI 配置 REST API 中的说明操作来将其导入 API Gateway 中。

创建一个可代入的 IAM 角色

为了确保您的 API 调用您的 Calc Lambda 函数,您将需要具有一个 API Gateway 可代入的 IAM 角色,这是一个具有以下信任关联的 IAM 角色:

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

您创建的角色将需要具有 Lambda InvokeFunction 权限。否则,API 调用方将收到 500 Internal Server Error 响应。要向该角色提供此权限,请将以下 IAM 策略附加到它:

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

以下是完成所有操作的方式:

创建 API Gateway 可代入的 IAM 角色
  1. 登录 IAM 控制台。

  2. 选择角色

  3. 选择创建角色

  4. 选择受信任实体的类型下,选择 AWS 服务

  5. 选择将使用此角色的服务下,选择 Lambda

  6. 选择下一步: 权限

  7. 选择创建策略

    新的创建策略控制台窗口将会打开。在该窗口中,执行以下操作:

    1. JSON 选项卡中,将现有策略替换为以下策略:

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "*" } ] }
    2. 选择查看策略

    3. 查看策略下,执行以下操作:

      1. 名称中,键入一个名称,如 lambda_execute

      2. 选择创建策略

  8. 在原来的创建角色控制台窗口中,执行以下操作:

    1. 从下拉列表的添加权限策略下,选择您的 lambda_execute 策略。

      如果您未在策略列表中看到您的策略,请选择列表顶部的刷新按钮。(请勿刷新浏览器页面!)

    2. 选择下一步: 标签

    3. 选择下一步: 审核

    4. 对于角色名称,键入一个名称,如 lambda_invoke_function_assume_apigw_role

    5. 选择创建角色

  9. 从角色列表中,选择您的 lambda_invoke_function_assume_apigw_role

  10. 选择信任关系选项卡。

  11. 选择编辑信任关系

  12. 使用以下策略替换现有策略:

    { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com", "apigateway.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
  13. 选择更新信任策略

  14. 请记下您刚刚创建的角色的角色 ARN。您以后将需要它。

创建 Calc Lambda 函数

接下来,您将使用 Lambda 控制台创建 Lambda 函数。

  1. 在 Lambda 控制台中,选择创建函数

  2. 选择从头开始创作

  3. 名称中,输入 Calc

  4. 运行时中,选择受支持的最新 Node.jsPython 运行时。

  5. 选择创建函数

  6. 在首选运行时中复制以下 Lambda 函数,并将其粘贴到 Lambda 控制台的代码编辑器中。

    Node.js
    export const handler = async function (event, context) { console.log("Received event:", JSON.stringify(event)); if ( event.a === undefined || event.b === undefined || event.op === undefined ) { return "400 Invalid Input"; } const res = {}; res.a = Number(event.a); res.b = Number(event.b); res.op = event.op; if (isNaN(event.a) || isNaN(event.b)) { return "400 Invalid Operand"; } switch (event.op) { case "+": case "add": res.c = res.a + res.b; break; case "-": case "sub": res.c = res.a - res.b; break; case "*": case "mul": res.c = res.a * res.b; break; case "/": case "div": if (res.b == 0) { return "400 Divide by Zero"; } else { res.c = res.a / res.b; } break; default: return "400 Invalid Operator"; } return res; };
    Python
    import json def lambda_handler(event, context): print(event) try: (event['a']) and (event['b']) and (event['op']) except KeyError: return '400 Invalid Input' try: res = { "a": float( event['a']), "b": float( event['b']), "op": event['op']} except ValueError: return '400 Invalid Operand' if event['op'] == '+': res['c'] = res['a'] + res['b'] elif event['op'] == '-': res['c'] = res['a'] - res['b'] elif event['op'] == '*': res['c'] = res['a'] * res['b'] elif event['op'] == '/': if res['b'] == 0: return '400 Divide by Zero' else: res['c'] = res['a'] / res['b'] else: return '400 Invalid Operator' return res
  7. 在“执行角色”下,选择选择现有角色

  8. 输入您之前创建的 lambda_invoke_function_assume_apigw_role 角色的角色 ARN。

  9. 选择部署

此函数需要来自 a 输入参数的两个操作数 (bop) 以及一个运算符 (event)。该输入是格式如下的 JSON 对象:

{ "a": "Number" | "String", "b": "Number" | "String", "op": "String" }

此函数会返回计算所得的结果 (c) 和输入。对于无效的输入,该函数将返回空值或“Invalid op”字符串作为结果。输出具有以下 JSON 格式:

{ "a": "Number", "b": "Number", "op": "String", "c": "Number" | "String" }

您应该先在 Lambda 控制台中测试该函数,然后再在下一步中将其与 API 集成。

测试 Calc Lambda 函数

以下内容介绍如何在 Lambda 控制台中测试您的 Calc 函数:

  1. 选择测试选项卡。

  2. 对于测试事件名称,请输入 calc2plus5

  3. 将测试事件定义替换为以下内容:

    { "a": "2", "b": "5", "op": "+" }
  4. 选择保存

  5. 选择测试

  6. 展开执行结果: 成功。您将看到以下内容:

    { "a": 2, "b": 5, "op": "+", "c": 7 }

创建 Calc API

以下过程介绍如何为您刚刚创建的 Calc Lambda 函数创建 API。在后续部分中,您将资源和方法添加到该 API。

创建 API
  1. 通过以下网址登录到 Amazon API Gateway 控制台:https://console.aws.amazon.com/apigateway

  2. 如果您是第一次使用 API Gateway,您会看到一个介绍服务特征的页面。在 REST API 下,选择生成。当创建示例 API 弹出框出现时,选择确定

    如果这不是您首次使用 API Gateway,请选择创建 API。在 REST API 下,选择生成

  3. 对于 API 名称,请输入 LambdaCalc

  4. (可选)对于描述,输入描述。

  5. API 端点类型设置保留为区域

  6. 选择 Create API (创建 API)

集成 1:创建使用查询参数的 GET 方法以调用 Lambda 函数

通过创建将查询字符串参数传递给 Lambda 函数的 GET 方法,启用要从浏览器中进行调用的 API。这种方法可能非常有用,特别是对于允许开放访问的 API。

创建 API 后,您将创建一个资源。通常情况下,根据应用程序逻辑将 API 资源组织成资源树形式。在此步骤中,您将创建一个 /calc 资源。

创建 /calc 资源
  1. 选择创建资源

  2. 代理资源保持为关闭状态。

  3. 资源路径保持为 /

  4. 对于资源名称,输入 calc

  5. CORS(跨源资源共享)保持为关闭状态。

  6. 选择创建资源

通过创建将查询字符串参数传递给 Lambda 函数的 GET 方法,启用要从浏览器中进行调用的 API。这种方法可能非常有用,特别是对于允许开放访问的 API。

在此方法中,Lambda 要求使用 POST 请求调用任何 Lambda 函数。此示例表明,前端方法请求中的 HTTP 方法可以与后端中的集成请求不同。

创建 GET 方法
  1. 选择 /calc 资源,然后选择创建方法

  2. 对于方法类型,选择 GET

  3. 对于集成类型,选择 AWS 服务

  4. 对于 AWS 区域,选择您创建 Lambda 函数的 AWS 区域。

  5. 对于 AWS 服务,选择 Lambda

  6. AWS 子域保留为空白。

  7. 对于 HTTP 方法,选择 POST

  8. 对于操作类型,选择使用路径覆盖。借助此选项,我们可以指定用来执行 Calc 函数的调用操作的 ARN。

  9. 对于路径覆盖,输入 2015-03-31/functions/arn:aws:lambda:us-east-2:account-id:function:Calc/invocations。对于 account-id,输入您的 AWS 账户 ID。对于 us-east-2,输入您创建 Lambda 函数的 AWS 区域。

  10. 对于执行角色,输入 lambda_invoke_function_assume_apigw_role 的角色 ARN。

  11. 请勿更改凭证缓存默认超时的设置。

  12. 选择方法请求设置

  13. 对于请求验证程序,选择验证查询字符串参数和标头

    如果客户端没有指定必需的参数,此设置将导致返回错误消息。

  14. 选择 URL 查询字符串参数

    现在,为 /calc 资源上的 GET 方法设置查询字符串参数,来代表后端 Lambda 函数接收输入。

    要创建查询字符串参数,请执行以下操作:

    1. 选择添加查询字符串

    2. 名称中,输入 operand1

    3. 打开必需

    4. 缓存保持为关闭状态。

    重复相同的步骤,创建一个名为 operand2 的查询字符串和一个名为 operator 的查询字符串。

  15. 选择创建方法

现在,创建映射模板,以将客户端提供的查询字符串转换为 Calc 函数需要的集成请求负载。此模板会将方法请求中声明的三个查询字符串参数映射为 JSON 对象的指定属性值,作为后端 Lambda 函数的输入。转换后的 JSON 对象将作为集成请求负载包含在内。

将输入参数映射到集成请求
  1. 集成请求选项卡的集成请求设置下,选择编辑

  2. 对于请求正文传递,选择当未定义模板时(推荐)

  3. 选择映射模板

  4. 选择添加映射模板

  5. 对于内容类型,输入 application/json

  6. 对于模板正文,输入以下代码:

    { "a": "$input.params('operand1')", "b": "$input.params('operand2')", "op": "$input.params('operator')" }
  7. 选择保存

现在,您可以测试 GET 方法来验证它是否已经过正确设置,可以调用 Lambda 函数。

测试 GET 方法
  1. 选择测试选项卡。您可能需要选择右箭头按钮,以显示该选项卡。

  2. 对于查询字符串,输入 operand1=2&operand2=3&operator=+

  3. 选择 Test (测试)

    结果应与如下显示类似:

    在 API Gateway 中创建 API 作为 Lambda 代理

集成 2:创建使用 JSON 负载的 POST 方法以调用 Lambda 函数

通过创建使用 JSON 负载的 POST 方法以调用 Lambda 函数完成此操作,以便客户端必须将必要的输入提供给请求正文中的后端函数。为确保客户端上传正确的输入数据,您将对负载启用请求验证。

创建使用 JSON 负载的 POST 方法
  1. 选择 /calc 资源,然后选择创建方法

  2. 对于方法类型,选择 POST

  3. 对于集成类型,选择 AWS 服务

  4. 对于 AWS 区域,选择您创建 Lambda 函数的 AWS 区域。

  5. 对于 AWS 服务,选择 Lambda

  6. AWS 子域保留为空白。

  7. 对于 HTTP 方法,选择 POST

  8. 对于操作类型,选择使用路径覆盖。借助此选项,我们可以指定用来执行 Calc 函数的调用操作的 ARN。

  9. 对于路径覆盖,输入 2015-03-31/functions/arn:aws:lambda:us-east-2:account-id:function:Calc/invocations。对于 account-id,输入您的 AWS 账户 ID。对于 us-east-2,输入您创建 Lambda 函数的 AWS 区域。

  10. 对于执行角色,输入 lambda_invoke_function_assume_apigw_role 的角色 ARN。

  11. 请勿更改凭证缓存默认超时的设置。

  12. 选择创建方法

现在,创建输入模型以描述输入数据结构和验证传入请求正文。

创建输入模型
  1. 在主导航窗格中,选择模型

  2. 选择创建模型

  3. 对于名称,请输入 input

  4. 对于内容类型,输入 application/json

    如果未找到匹配的内容类型,则不执行请求验证。要使用同一模型而不考虑内容类型,请输入 $default

  5. 对于模型架构,输入以下模型:

    { "type":"object", "properties":{ "a":{"type":"number"}, "b":{"type":"number"}, "op":{"type":"string"} }, "title":"input" }
  6. 选择创建模型

现在,创建输出模型。此模型描述了后端计算得出的输出的数据结构。它可用于将集成响应数据映射到不同的模型。本教程依靠传递行为,并不会使用此模型。

创建输出模型
  1. 选择创建模型

  2. 对于名称,请输入 output

  3. 对于内容类型,输入 application/json

    如果未找到匹配的内容类型,则不执行请求验证。要使用同一模型而不考虑内容类型,请输入 $default

  4. 对于模型架构,输入以下模型:

    { "type":"object", "properties":{ "c":{"type":"number"} }, "title":"output" }
  5. 选择创建模型

现在,创建结果模型。此模型描述了返回响应数据的数据结构。它同时引用您的 API 中定义的输入输出架构。

创建结果模型
  1. 选择创建模型

  2. 对于名称,请输入 result

  3. 对于内容类型,输入 application/json

    如果未找到匹配的内容类型,则不执行请求验证。要使用同一模型而不考虑内容类型,请输入 $default

  4. 对于模型架构,使用您的 restapi-id 输入以下模型。您的 restapi-id 用括号列在控制台顶部,可通过以下流程找到:API Gateway > APIs > LambdaCalc (abc123).

    { "type":"object", "properties":{ "input":{ "$ref":"https://apigateway.amazonaws.com/restapis/restapi-id/models/input" }, "output":{ "$ref":"https://apigateway.amazonaws.com/restapis/restapi-id/models/output" } }, "title":"result" }
  5. 选择创建模型

现在,配置 POST 方法的方法请求,以便在传入的请求正文上启用请求验证。

在 POST 方法上启用请求验证
  1. 在主导航窗格中,选择资源,然后从资源树中选择 POST 方法。

  2. 方法请求选项卡上的方法请求设置下,选择编辑

  3. 对于请求验证程序,选择验证正文

  4. 选择请求正文,然后选择添加模型

  5. 对于内容类型,输入 application/json

    如果未找到匹配的内容类型,则不执行请求验证。要使用同一模型而不考虑内容类型,请输入 $default

  6. 对于模型,选择输入

  7. 选择保存

现在,您可以测试 POST 方法来验证它是否已经过正确设置,可以调用 Lambda 函数。

测试 POST 方法
  1. 选择测试选项卡。您可能需要选择右箭头按钮,以显示该选项卡。

  2. 对于请求正文,输入以下 JSON 负载。

    { "a": 1, "b": 2, "op": "+" }
  3. 选择测试

    您应看到以下输出:

    { "a": 1, "b": 2, "op": "+", "c": 3 }

集成 3:创建使用路径参数的 GET 方法以调用 Lambda 函数

现在,您将在由一系列路径参数指定的资源上创建一个 GET 方法,以调用后端 Lambda 函数。路径参数值指定 Lambda 函数的输入数据。您将使用映射模板,将传入路径参数值映射到必需的集成请求负载。

生成的 API 资源结构将如下所示:

在 API Gateway 中创建 API 作为 Lambda 代理
创建 /{operand1}/{operand2}/{operator} 资源
  1. 选择创建资源

  2. 对于资源路径,选择 /calc

  3. 对于资源名称,输入 {operand1}

  4. CORS(跨源资源共享)保持为关闭状态。

  5. 选择创建资源

  6. 对于资源路径,选择 /calc/{operand1}/

  7. 对于资源名称,输入 {operand2}

  8. CORS(跨源资源共享)保持为关闭状态。

  9. 选择创建资源

  10. 对于资源路径,选择 /calc/{operand1}/{operand2}/

  11. 对于资源名称,输入 {operator}

  12. CORS(跨源资源共享)保持为关闭状态。

  13. 选择创建资源

这次,您将在 API Gateway 控制台中使用内置的 Lambda 集成来设置方法集成。

设置方法集成
  1. 选择 /{operand1}/{operand2}/{operator} 资源,然后选择创建方法

  2. 对于方法类型,选择 GET

  3. 对于集成类型,选择 Lambda

  4. 保持 Lambda 代理集成处于关闭状态。

  5. 对于 Lambda 函数,选择您创建 Lambda 函数的 AWS 区域,并输入 Calc

  6. 默认超时保持为开启状态。

  7. 选择创建方法

现在,创建映射模板,以将创建 /calc/{operand1}/{operand2}/{operator} 资源时声明的三个 URL 路径参数映射到 JSON 对象中的指定属性值。由于 URL 路径必须经过 URL 编码,必须将除法运算符指定为 %2F,而不是 /。此模板先将 %2F 转换为 '/',然后再将其发送到 Lambda 函数。

创建映射模板
  1. 集成请求选项卡的集成请求设置下,选择编辑

  2. 对于请求正文传递,选择当未定义模板时(推荐)

  3. 选择映射模板

  4. 对于内容类型,输入 application/json

  5. 对于模板正文,输入以下代码:

    { "a": "$input.params('operand1')", "b": "$input.params('operand2')", "op": #if($input.params('operator')=='%2F')"/"#{else}"$input.params('operator')"#end }
  6. 选择保存

现在,您可以测试 GET 方法来验证它是否已经过正确设置,无需映射即可通过集成响应调用 Lambda 函数并传递原始输出。

测试 GET 方法
  1. 选择测试选项卡。您可能需要选择右箭头按钮,以显示该选项卡。

  2. 对于路径,请执行以下操作:

    1. 对于 operand1,输入 1

    2. 对于 operand2,输入 1

    3. 对于 operator,输入 +

  3. 选择 Test (测试)

  4. 结果应该如下所示:

    在 API Gateway 控制台中测试 GET 方法。

接下来,根据 result 架构对方法响应负载的数据结构进行建模。

默认情况下,系统会为方法响应正文分配一个空白模型。这将在不映射的情况下传递集成响应正文。但是,当您为一种强类型语言(例如 Java 或 Objective-C)生成一个开发工具包时,您的开发工具包用户会收到一个空白对象作为结果。为确保 REST 客户端和开发工具包客户端能收到期望的结果,您必须使用预定义的架构为响应数据建模。在这里,您将为方法响应正文定义一个模型,并构建一个映射模板,以便将集成响应正文转换为方法响应正文。

创建方法响应
  1. 方法响应选项卡的响应 200 下,选择编辑

  2. 响应正文下,选择添加模型

  3. 对于内容类型,输入 application/json

  4. 对于模型,选择结果

  5. 选择保存

为方法响应正文设置模型可以确保将响应数据转换为给定开发工具包的 result 对象。要确保对集成响应数据进行相应的映射,您将需要一个映射模板。

创建映射模板
  1. 集成响应选项卡上的默认 - 响应下,选择编辑

  2. 选择映射模板

  3. 对于内容类型,输入 application/json

  4. 对于模板正文,输入以下代码:

    #set($inputRoot = $input.path('$')) { "input" : { "a" : $inputRoot.a, "b" : $inputRoot.b, "op" : "$inputRoot.op" }, "output" : { "c" : $inputRoot.c } }
  5. 选择保存

测试映射模板
  1. 选择测试选项卡。您可能需要选择右箭头按钮,以显示该选项卡。

  2. 对于路径,请执行以下操作:

    1. 对于 operand1,输入 1

    2. 对于 operand2,输入 2

    3. 对于 operator,输入 +

  3. 选择测试

  4. 结果将类似于以下内容:

    { "input": { "a": 1, "b": 2, "op": "+" }, "output": { "c": 3 } }

目前,您只能在 API Gateway 控制台中通过测试功能调用 API。要使 API 可用于客户端,您将需要部署 API。每当您添加、修改或删除资源和方法、更新数据映射或者更新阶段设置时,请始终确保重新部署 API。否则,新功能或更新将不可用于您 API 的客户端。如以下所示:

部署 API
  1. 选择部署 API

  2. 对于阶段,选择新建阶段

  3. 对于阶段名称,输入 Prod

  4. (可选)对于描述,输入描述。

  5. 选择部署

  6. (可选)在阶段详细信息下,对于调用 URL,您可以选择复制图标以复制您 API 的调用 URL。您可以将此值与 PostmancURL 等工具结合使用来测试您的 API。

注意

每当您添加、修改或删除资源或方法、更新数据映射或者更新阶段设置时,请务必重新部署 API。否则,新特征或更新将不可用于您的 API 的客户端。