在 API Gateway 中设置方法请求 - Amazon API Gateway
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

在 API Gateway 中设置方法请求

设置方法请求涉及在创建RestApi资源之后执行以下任务:

  1. 创建新的 API 或选择现有的 API 资源实体。

  2. 创建特定于新创建或选定的 API Resource 上的 HTTP 动词的 API 方法资源。此任务可进一步分为以下子任务:

    • 为方法请求添加 HTTP 方法

    • 配置请求参数

    • 定义请求正文的模型

    • 制定授权方案

    • 启用请求验证

您可以使用以下方法执行这些任务:

有关使用这些工具的示例,请参阅 初始化 API Gateway 中的 REST API 设置

设置 API 资源

在 API Gateway API 中,您通过 API 资源实体树公开可寻址的资源,树的根资源 (/) 位于层次结构顶部。根资源相对于 API 的基本 URL,其中包含 API 终端节点和阶段名称。在 API Gateway 控制台中,该基本 URI 称为调用 URI,会在 API 部署后在 API 的阶段编辑器中显示。

API 终端节点可以是默认主机名或自定义域名。默认主机名采用以下格式:

{api-id}.execute-api.{region}.amazonaws.com

在此格式中,{api-id} 表示 API Gateway 生成的 API 标识符。{region} 变量表示您在创建 API 时选择的 Amazon 区域(例如 us-east-1)。自定义域名是有效 Internet 域的便于用户识别的任何名称。例如,如果您已经注册 Internet 域 example.com,任何 *.example.com 都是有效的自定义域名。有关更多信息,请参阅创建自定义域名

对于PetStore 示例 API,根资源 (/) 公开了宠物商店。/pets 资源表示 Pet Store 中提供的宠物集合。/pets/{petId} 公开指定标识符 (petId) 的单个宠物。{petId} 的路径参数是请求参数的一部分。

要设置 API 资源,您可以选择现有资源作为父资源,然后在此父资源下创建子资源。您开始时将根资源作为父资源,向此父资源添加资源,向这个子资源添加另一个资源作为新的父资源,依此类推,直到添加到其父标识符。然后将命名的资源添加到父资源。

使用 Amazon CLI,您可以调用get-resources命令来查看 API 的哪些资源可用:

aws apigateway get-resources --rest-api-id <apiId> \ --region <region>

结果是当前可用的 API 资源的列表。对于我们的 PetStore 示例 API,此列表如下所示:

{ "items": [ { "path": "/pets", "resourceMethods": { "GET": {} }, "id": "6sxz2j", "pathPart": "pets", "parentId": "svzr2028x8" }, { "path": "/pets/{petId}", "resourceMethods": { "GET": {} }, "id": "rjkmth", "pathPart": "{petId}", "parentId": "6sxz2j" }, { "path": "/", "id": "svzr2028x8" } ] }

每个项目都列出了资源 (id) (根资源除外) 的标识符、其直接父级 (parentId) 以及资源名称 (pathPart)。根资源的特殊之处在于不具有任何父级。选择某个资源作为父资源之后,调用以下命令添加子资源。

aws apigateway create-resource --rest-api-id <apiId> \ --region <region> \ --parent-id <parentId> \ --path-part <resourceName>

例如,要在 PetStore 网站上添加待售的宠物食品,请通过设置为foodpath-partparent-id向根目录 (/) 添加food资源svzr2028x8。结果类似于以下内容:

{ "path": "/food", "pathPart": "food", "id": "xdsvhp", "parentId": "svzr2028x8" }

使用代理资源来简化 API 设置

随着业务的增长, PetStore 所有者可能会决定添加食品、玩具和其他与宠物相关的物品进行出售。为此,您可在根资源下添加 /food/toys 和其他资源。在每个销售类别下,您可能还需要添加更多资源,例如 /food/{type}/{item}/toys/{type}/{item} 等。这很麻烦。如果您决定在资源路径中添加一个中间层 {subtype} 以将路径层次结构更改为 /food/{type}/{subtype}/{item}/toys/{type}/{subtype}/{item} 等,这些更改将会中断现有的 API 设置。为了避免这种情况,您可以使用 API Gateway 代理资源一次性公开一组 API 资源。

API Gateway 将代理资源定义为要在提交请求时指定的资源的占位符。代理资源用 {proxy+} 的特殊路径参数表示,该路径通常被称为“贪婪”路径参数。+ 号表示其附加了哪些子资源。/parent/{proxy+} 占位符表示与 /parent/* 路径模式匹配的任何资源。“贪婪”路径参数名称 proxy 可以按照与处理常规路径参数名称相同的方法用其他字符串替换。

使用 Amazon CLI,您可以调用以下命令在 root (/{proxy+}) 下设置代理资源:

aws apigateway create-resource --rest-api-id <apiId> \ --region <region> \ --parent-id <rootResourceId> \ --path-part {proxy+}

结果类似于以下内容:

{ "path": "/{proxy+}", "pathPart": "{proxy+}", "id": "234jdr", "parentId": "svzr2028x8" }

对于 PetStore API 示例,您可以使用 /{proxy+} 表示 /pets/pets/{petId}。此代理资源还可以引用任何其他(现有或 to-be-added)资源/food/{type}/{item},例如/toys/{type}/{item}、等、或/food/{type}/{subtype}/{item}/toys/{type}/{subtype}/{item}、等。后端开发人员确定资源层次结构,客户端开发人员负责了解此结构。API Gateway 会将客户端提交的内容传递到后端。

API 可以包含多个代理资源。例如,API 中允许包含以下代理资源。

/{proxy+} /parent/{proxy+} /parent/{child}/{proxy+}

如果代理资源具有非代理同级资源,则会从代理资源的表示形式中排除同级资源。在前面的示例中,/{proxy+} 是指除 /parent[/*] 资源之外的根资源下的任何资源。换言之,针对特定资源的方法请求优先于针对同一资源层次结构级别的通用资源的方法请求。

代理资源不能包含任何子资源。{proxy+} 后面的任何 API 资源都是冗余和不确定的资源。API 中不允许包含以下代理资源。

/{proxy+}/child /parent/{proxy+}/{child} /parent/{child}/{proxy+}/{grandchild+}

设置 HTTP 方法

API 方法请求通过 API Gateway 方法资源进行封装。要设置方法请求,您必须先实例化 Method 资源,设置至少一个 HTTP 方法和方法的授权类型。

API Gateway 与代理资源密切相关,支持 HTTP 方法 ANY。此 ANY 方法表示将在运行时提供的任何 HTTP 方法。它允许您将单个 API 方法设置用于 DELETEGETHEADOPTIONSPATCHPOSTPUT 支持的所有 HTTP 方法。

您也可以在非代理资源上设置 ANY 方法。通过将 ANY 方法与代理资源组合使用,即可获得适用于针对 API 的任何资源所支持的所有 HTTP 方法的单个 API 方法设置。此外,后端可以发展变化,而不会中断现有的 API 设置。

设置 API 方法之前,请考虑谁可以调用此方法。根据您的计划设置授权类型。对于开放式访问,将其设置为 NONE。要使用 IAM 权限,请将授权类型设置为 AWS_IAM。要使用 Lambda 授权方函数,请将此属性设置为 CUSTOM。要使用 Amazon Cognito 用户池,请将授权类型设置为 COGNITO_USER_POOLS

以下 Amazon CLI 命令显示如何使用 IAM 权限来控制其访问权限,针对指定资源 (6sxz2j) 创建ANY动词的方法请求。

aws apigateway put-method --rest-api-id vaz7da96z6 \ --resource-id 6sxz2j \ --http-method ANY \ --authorization-type AWS_IAM \ --region us-west-2

要创建使用不同授权类型的 API 方法请求,请参阅设置方法请求授权

设置方法请求参数

方法请求参数是一种客户端提供完成方法请求所需的输入数据或执行上下文的方式。方法参数可以是路径参数、标头或查询字符串参数。在方法请求设置期间,您必须声明必需的请求参数,使其可供客户端使用。对于非代理集成,您可以将这些请求参数转换为与后端要求兼容的形式。

例如,对于 GET /pets/{petId} 方法请求,{petId} 路径变量为必需的请求参数。您可在调用 Amazon CLI的 put-method 命令时声明此路径参数。下文对此进行了说明:

aws apigateway put-method --rest-api-id vaz7da96z6 \ --resource-id rjkmth \ --http-method GET \ --authorization-type "NONE" \ --region us-west-2 \ --request-parameters method.request.path.petId=true

如果参数不是必需的,则可在 false 中将其设置为 request-parameters。例如,如果 GET /pets 方法使用 type 的可选查询字符串参数和 breed 的可选标头参数,您可以使用以下 CLI 命令声明它们,假设 /pets 资源 id6sxz2j

aws apigateway put-method --rest-api-id vaz7da96z6 \ --resource-id 6sxz2j \ --http-method GET \ --authorization-type "NONE" \ --region us-west-2 \ --request-parameters method.request.querystring.type=false,method.request.header.breed=false

如果不使用这种缩写形式,您可以使用 JSON 字符串来设置 request-parameters 值:

'{"method.request.querystring.type":false,"method.request.header.breed":false}'

使用此设置,客户端可以按照类型查询宠物:

GET /pets?type=dog

客户端可以按照以下所示查询贵宾品种的狗:

GET /pets?type=dog breed:poodle

有关如何将方法请求参数映射到集成请求参数的信息,请参阅设置 REST API 集成

设置方法请求模型

对于可在负载中获取输入数据的 API 方法,您可以使用模型。模型采用 JSON 架构草案 4 表示,描述了请求正文的数据结构。借助模型,客户端可以确定如何构建方法请求负载以作为输入。更重要的是,API Gateway 使用模型来验证请求生成开发工具包以及初始化用于在 API Gateway 控制台中设置集成的映射模板。有关如何创建模型的信息,请参阅了解数据模型

根据内容类型,该方法负载可以具有不同格式。模型根据应用负载的媒体类型来编制索引。API Gateway 使用 Content-Type 请求标头来确定内容类型。要设置方法请求模型,请在调用命令时将该"<media-type>":"<model-name>"格式的键值对添加到requestModels映射中 Amazon CLI put-method

要使用同一模型而不考虑内容类型,请指定 $default 作为键。

例如,要在示 PetStore 例 API 的POST /pets方法请求的 JSON 负载上设置模型,可以调用以下 Amazon CLI 命令:

aws apigateway put-method \ --rest-api-id vaz7da96z6 \ --resource-id 6sxz2j \ --http-method POST \ --authorization-type "NONE" \ --region us-west-2 \ --request-models '{"application/json":"petModel"}'

其中,petModel 是描述宠物的 name 资源的 Model 属性值。实际架构定义采用 schema 资源的 Model 属性的 JSON 字符串值表示。

在 Java 或 API 的其他强类型开发工具包中,输入数据将强制转换为派生自架构定义的 petModel 类。使用请求模型,生成的开发工具包中的输入数据将强制转换为派生自默认 Empty 模型的 Empty 类。在这种情况下,客户端无法实例化正确的数据类以提供所需的输入。

设置方法请求授权

要控制哪些人员可以调用 API 方法,您可在方法中配置授权类型。您可以使用此类型制定其中一个支持的授权方,包括 IAM 角色和策略 (AWS_IAM)、Amazon Cognito 用户池 (COGNITO_USER_POOLS) 或 Lambda 授权方 (CUSTOM)。

要使用 IAM 权限为 API 方法授予访问权限,请将 authorization-type 输入属性设置为 AWS_IAM。当您设置此选项时,API Gateway 将根据调用方的凭证验证调用方对请求的签名。如果经验证的用户有权调用此方法,它将接受请求。否则,它将拒绝请求,而调用方会收到未经授权的错误响应。除非调用方有权调用 API 方法,否则对该方法的调用不会成功。以下 IAM policy 向调用方授予权限,以调用在相同 Amazon Web Services 账户中创建的任何 API 方法:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "execute-api:Invoke" ], "Resource": "arn:aws:execute-api:*:*:*" } ] }

有关更多信息,请参阅使用 IAM 权限控制对 API 的访问

目前,您只能向 API 所有者的 Amazon Web Services 账户内的用户、组和角色授予此策略。只有当允许其他 Amazon Web Services 账户 用户在 API 所有者中扮演 Amazon Web Services 账户 具有调用execute-api:Invoke操作所需权限的角色时,才能调用 API 方法。有关跨账户权限的信息,请参阅使用 IAM 角色

你可以使用 Amazon CLI Amazon SDK 或 REST API 客户端,例如 Postman,它实现了签名版本 4 签名

要使用 Lambda 授权方来授予对 API 方法的访问权限,请将 authorization-type 输入属性设置为 CUSTOM,并将 authorizer-id 输入属性设置为已存在的 Lambda 授权方的 id 属性值。引用的 Lambda 授权方可以是 TOKENREQUEST 类型。有关创建 Lambda 授权方的信息,请参阅 使用 API Gateway Lambda 授权方

要使用 Amazon Cognito 用户池来授予对 API 方法的访问权限,请将 authorization-type 输入属性设置为 COGNITO_USER_POOLS,并将 authorizer-id 输入属性设置为已创建的 COGNITO_USER_POOLS 授权方的 id 属性值。有关创建 Amazon Cognito 用户池授权方的信息,请参阅 使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问

设置方法请求验证

您可在设置 API 方法请求时启用请求验证。您需要先创建请求验证程序

aws apigateway create-request-validator \ --rest-api-id 7zw9uyk9kl \ --name bodyOnlyValidator \ --validate-request-body \ --no-validate-request-parameters

此 CLI 命令创建仅限正文的请求验证程序。输出示例如下:

{ "validateRequestParameters": false, "validateRequestBody": true, "id": "jgpyy6", "name": "bodyOnlyValidator" }

使用此请求验证程序,您可在方法请求设置期间启用请求验证:

aws apigateway put-method \ --rest-api-id 7zw9uyk9kl --region us-west-2 --resource-id xdsvhp --http-method PUT --authorization-type "NONE" --request-parameters '{"method.request.querystring.type": false, "method.request.querystring.page":false}' --request-models '{"application/json":"petModel"}' --request-validator-id jgpyy6

要包含在请求验证中,必须将请求参数声明为必需参数。如果在请求验证中使用了该页面的查询字符串参数,则必须将前述示例的 request-parameters 映射指定为 '{"method.request.querystring.type": false, "method.request.querystring.page":true}'