

# 在 API Gateway 中设置方法请求
<a name="api-gateway-method-settings-method-request"></a>

设置方法请求涉及在创建 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源之后执行以下任务：

1.  创建新的 API 或选择现有的 API [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)实体。

1.  创建特定于新创建或选定的 API `Resource` 上的 HTTP 动词的 API [方法](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html)资源。此任务可进一步分为以下子任务：
   +  为方法请求添加 HTTP 方法
   +  配置请求参数
   +  定义请求正文的模型
   +  制定授权方案
   +  启用请求验证 

您可以使用以下方法执行这些任务：
+  [API Gateway 控制台](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)
+  AWS CLI 命令 ([create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 和 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html))
+  AWS 开发工具包函数（例如 Node.js 中的 [createResource](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#createResource-property) 和 [putMethod](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#putMethod-property)）
+  API Gateway REST API（[resource:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateResource.html) 和 [method:put](https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html)）。

**Topics**
+ [设置 API 资源](#setup-method-resources)
+ [设置 HTTP 方法](#setup-method-add-http-method)
+ [设置方法请求参数](#setup-method-request-parameters)
+ [设置方法请求模型](#setup-method-request-model)
+ [设置方法请求授权](#setup-method-request-authorization)
+ [设置方法请求验证](#setup-method-request-validation)

## 设置 API 资源
<a name="setup-method-resources"></a>

在 API Gateway API 中，您通过 API [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_GetResources.html)实体树公开可寻址的资源，树的根资源 (`/`) 位于层次结构顶部。根资源相对于 API 的基本 URL，其中包含 API 端点和阶段名称。在 API Gateway 控制台中，该基本 URI 称为**调用 URI**，会在 API 部署后在 API 的阶段编辑器中显示。

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

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

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

对于 [PetStore 示例 API](api-gateway-create-api-from-example.md)，根资源 (`/`) 用于公开 Pet Store。`/pets` 资源表示 Pet Store 中提供的宠物集合。`/pets/{petId}` 公开指定标识符 (`petId`) 的单个宠物。`{petId}` 的路径参数是请求参数的一部分。

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

以下 [get-resources](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-resources.html) 命令检索 API 的所有资源：

```
aws apigateway get-resources --rest-api-id apiId
```

对于 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 \
    --parent-id parentId \
    --path-part resourceName
```

例如，在 PetStore 网站上添加要销售的宠物食品时，请使用以下命令：

```
aws apigateway create-resource --rest-api-id a1b2c3 \
    --parent-id svzr2028x8 \
    --path-part food
```

输出将与以下内容类似：

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

### 使用代理资源来简化 API 设置
<a name="api-gateway-proxy-resource"></a>

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

API Gateway 将代理资源定义为要在提交请求时指定的资源的占位符。代理资源用 `{proxy+}` 的特殊路径参数表示，该路径通常被称为“贪婪”路径参数。`+` 号表示其附加了哪些子资源。`/parent/{proxy+}` 占位符表示与 `/parent/*` 路径模式匹配的任何资源。您可以使用任意字符串作为贪婪路径参数名称。

以下 [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 命令在根目录下（`/{proxy+}`）创建代理资源：

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

输出将与以下内容类似：

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

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

API 可以包含多个代理资源。例如，假设 `/parent/{proxy+}` 与 `/parent/{child}/{proxy+}` 不是同一个父级，API 中支持以下代理资源。

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

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

下表显示了对于 API 的 `prod` 阶段，API Gateway 如何将请求路由到以下资源。

```
ANY /{proxy+}
GET /pets/{proxy+}
GET /pets/dog
```


| 请求 | 选定的路由 | 说明 | 
| --- | --- | --- | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/pets/dog`  |  `GET /pets/dog`  |  请求与此资源完全匹配。  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/pets/cats`  |  `GET /pets/{proxy+}`  |  `/pets/{proxy+}` 贪婪路径变量捕获此请求。  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/animals`  |  `GET /{proxy+}`  |  `/{proxy+}` 贪婪路径变量捕获此请求。  | 

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

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

## 设置 HTTP 方法
<a name="setup-method-add-http-method"></a>

API 方法请求通过 API Gateway [方法](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html)资源进行封装。要设置方法请求，您必须先实例化 `Method` 资源，设置至少一个 HTTP 方法和方法的授权类型。

API Gateway 与代理资源密切相关，支持 HTTP 方法 `ANY`。此 `ANY` 方法表示将在运行时提供的任何 HTTP 方法。它允许您将单个 API 方法设置用于 `DELETE`、`GET`、`HEAD`、`OPTIONS`、`PATCH`、`POST` 和 `PUT` 支持的所有 HTTP 方法。

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

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

以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令为 `ANY` 动词创建方法请求，使用 IAM 权限控制其访问权限。

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method ANY \
    --authorization-type AWS_IAM
```

要创建使用不同授权类型的 API 方法请求，请参阅[设置方法请求授权](#setup-method-request-authorization)。

## 设置方法请求参数
<a name="setup-method-request-parameters"></a>

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

例如，对于 `GET /pets/{petId}` 方法请求，`{petId}` 路径变量为必需的请求参数。您可在调用 `put-method` 的 AWS CLI 命令时声明此路径参数。以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建带有所需路径参数的方法：

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

如果参数不是必需的，则可在 `false` 中将其设置为 `request-parameters`。例如，如果 `GET /pets` 方法使用 `type` 的可选查询字符串参数以及 `age` 的可选标头参数，则您可以使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令声明它们：

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method GET \
    --authorization-type "NONE" \
    --request-parameters method.request.querystring.type=false,method.request.header.age=false
```

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

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

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

```
GET /pets?type=dog
```

 客户端可如下所示查询狗狗中的幼犬：

```
GET /pets?type=dog
age:puppy
```

有关如何将方法请求参数映射到集成请求参数的信息，请参阅[针对 API Gateway 中的 REST API 的集成](how-to-integration-settings.md)。

## 设置方法请求模型
<a name="setup-method-request-model"></a>

对于可在负载中获取输入数据的 API 方法，您可以使用模型。模型采用 [JSON 架构草案 4](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) 表示，描述了请求正文的数据结构。借助模型，客户端可以确定如何构建方法请求负载以作为输入。更重要的是，API Gateway 使用模型来[验证请求](api-gateway-method-request-validation.md)、[生成开发工具包](how-to-generate-sdk.md)以及初始化用于在 API Gateway 控制台中设置集成的映射模板。有关如何创建[模型](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html)的信息，请参阅[了解数据模型](models-mappings-models.md)。

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

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

例如，对于 PetStore 示例 API，要在 `POST /pets` 方法请求的 JSON 有效载荷上设置模型，您可以调用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令：

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

其中，`petModel` 是描述宠物的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) 资源的 `Model` 属性值。实际架构定义采用 `schema` 资源的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html#schema](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html#schema) 属性的 JSON 字符串值表示。

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



## 设置方法请求授权
<a name="setup-method-request-authorization"></a>



 要控制哪些人员可以调用 API 方法，您可在方法中配置[授权类型](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizationType)。您可以使用此类型制定其中一个支持的授权方，包括 IAM 角色和策略 (`AWS_IAM`)、Amazon Cognito 用户池 (`COGNITO_USER_POOLS`) 或 Lambda 授权方 (`CUSTOM`)。

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

------
#### [ JSON ]

****  

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

------

有关更多信息，请参阅 [使用 IAM 权限控制对 REST API 的访问](permissions.md)。

目前，您只能向 API 所有者的 AWS 账户 内的用户、组和角色授予此策略。来自不同 AWS 账户 的用户只有在被允许代入 API 所有者的 AWS 账户 中的角色并具有调用 `execute-api:Invoke` 操作所需的权限时，才能调用 API 方法。有关跨账户权限的信息，请参阅[使用 IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html)。

您可以使用 AWS CLI、AWS SDK 或 REST API 客户端（例如 [Postman](https://www.postman.com/)），这将实施[签名版本 4（SigV4）签名](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html)。

要使用 Lambda 授权方来授予对 API 方法的访问权限，请将 `authorization-type` 输入属性设置为 `CUSTOM`，并将 [https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId) 输入属性设置为已存在的 Lambda 授权方的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id) 属性值。引用的 Lambda 授权方可以是 `TOKEN` 或 `REQUEST` 类型。有关创建 Lambda 授权方的信息，请参阅 [使用 API Gateway Lambda 授权方](apigateway-use-lambda-authorizer.md)。

要使用 Amazon Cognito 用户池来授予对 API 方法的访问权限，请将 `authorization-type` 输入属性设置为 `COGNITO_USER_POOLS`，并将 [https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId) 输入属性设置为已创建的 `COGNITO_USER_POOLS` 授权方的 [https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id) 属性值。有关创建 Amazon Cognito 用户池授权方的信息，请参阅 [使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问](apigateway-integrate-with-cognito.md)。

## 设置方法请求验证
<a name="setup-method-request-validation"></a>

您可在设置 API 方法请求时启用请求验证。您需要先创建[请求验证程序](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html)。以下 [create-request-validator](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-request-validator.html) 命令创建仅限正文的请求验证程序。

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

输出将与以下内容类似：

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

您可以使用此请求验证程序，在方法请求设置期间使用请求验证。以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建方法请求，该请求要求传入的请求正文与 `PetModel` 匹配，并且有两个并非必需的请求参数：

```
aws apigateway put-method \
    --rest-api-id 7zw9uyk9kl \
    --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
```

要在请求验证中包含某个请求参数，对于请求验证程序，您必须将 `validateRequestParameters` 设置为 `true`，并在 `put-method` 命令中将特定请求参数设置为 `true`。