

# 针对 API Gateway 中的 REST API 的请求验证
<a name="api-gateway-method-request-validation"></a>

 您可以配置 API Gateway，使其在处理集成请求之前对 API 请求执行基本验证。如果验证失败，API Gateway 会立即取消请求、向调用方返回 400 错误响应，并在 CloudWatch Logs 中发布验证结果。这可以减少对后端进行的不必要调用。更重要的是，它可以让您把精力集中在特定于应用程序的验证工作上。您可以通过验证所需请求参数是否有效并且不为空，或为更复杂的数据验证指定一个模型架构，从而验证请求正文。

**Topics**
+ [API Gateway 中的基本请求验证概览](#api-gateway-request-validation-basic-definitions)
+ [针对 REST API 的数据模型](models-mappings-models.md)
+ [在 API Gateway 中设置基本请求验证](api-gateway-request-validation-set-up.md)
+ [AWS CloudFormation 模板，提供带有基本请求验证的示例 API](api-gateway-request-validation-sample-cloudformation.md)

## API Gateway 中的基本请求验证概览
<a name="api-gateway-request-validation-basic-definitions"></a>

 API Gateway 可以执行基本请求验证，以便您可以专注于后端的应用程序特定验证。进行验证时，API Gateway 验证以下一项或两项条件：
+ 传入请求的 URI、查询字符串和标头中带有所需的请求参数且都不为空。API Gateway 仅检查参数是否存在，而不检查类型或格式。
+  适用的请求有效载荷遵循对应于给定内容类型的方法的已配置 [JSON schema](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) 请求。如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请将数据模型的内容类型设置为 `$default`。

要开启验证，您需要在[请求验证程序](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html)中指定验证规则，将验证程序添加到 API 的[请求验证程序的映射](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html)中，并将验证程序分配给各个 API 方法。

**注意**  
请求正文验证和[API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)是两个独立的主题。当请求负载没有匹配的模型架构时，可以选择传递或阻止原始负载。有关更多信息，请参阅 [API Gateway 中适用于 REST API 且无映射模板的有效载荷的方法请求行为](integration-passthrough-behaviors.md)。

# 针对 REST API 的数据模型
<a name="models-mappings-models"></a>

在 API Gateway 中，模型定义负载的数据结构。在 API Gateway 中，使用 [JSON 架构草案 4](https://tools.ietf.org/html/draft-zyp-json-schema-04) 定义模型。以下 JSON 对象是 Pet Store 示例中的示例数据。

```
{
    "id": 1,
    "type": "dog",
    "price": 249.99
}
```

数据包含宠物的 `id`、`type` 和 `price`。这些数据的模型允许您：
+ 使用基本请求验证。
+ 创建用于数据转换的映射模板。
+ 生成 SDK 时创建用户定义的数据类型（UDT）。

![\[PetStore API 的示例 JSON 数据模型。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/how-to-validate-requests.png)


在这个模型中：

1. `$schema` 对象表示一个有效的 JSON 架构版本标识符。此架构为 JSON 架构草案 v4。

1. `title` 对象是人类可读的模型标识符。此标题是 `PetStoreModel`。

1.  `required` 验证关键字要求使用 `type` 和 `price` 进行基本请求验证。

1. 模型的 `properties` 为 `id`、`type` 和 `price`。每个对象都有模型中描述的属性。

1. 对象 `type` 只能具有值 `dog`、`cat` 或 `fish`。

1. 对象 `price` 是一个数字，并受 `minimum` 为 25 和 `maximum` 为 500 所限制。

## PetStore 模型
<a name="PetStore-model-text"></a>

```
1 {
2 "$schema": "http://json-schema.org/draft-04/schema#",
3  "title": "PetStoreModel",
4  "type" : "object",
5  "required" : [ "price", "type" ],
6  "properties" : {
7    "id" : {
8      "type" : "integer"
9    },
10    "type" : {
11      "type" : "string",
12      "enum" : [ "dog", "cat", "fish" ]
13    },
14    "price" : {
15      "type" : "number",
16      "minimum" : 25.0,
17      "maximum" : 500.0
18    }
19  }
20 }
```

在这个模型中：

1. 在第 2 行上，`$schema` 对象表示一个有效的 JSON 架构版本标识符。此架构为 JSON 架构草案 v4。

1. 在第 3 行上，`title` 对象是用户可读的模型标识符。此标题是 `PetStoreModel`。

1.  在第 5 行上，`required` 验证关键字要求使用 `type` 和 `price` 进行基本请求验证。

1.  在第 6 -- 17 行上，模型的 `properties` 为 `id`、`type` 和 `price`。每个对象都有模型中描述的属性。

1. 在第 12 行上，对象 `type` 只能具有值 `dog`、`cat` 或 `fish`。

1. 在第 14 -- 17 行上，对象 `price` 是一个数字，并受 `minimum` 为 25 和 `maximum` 为 500 所限制。

## 创建更复杂的模型
<a name="api-gateway-request-validation-model-more-complex"></a>

 您可以使用 `$ref` 基元为较长的模型创建可重复使用的定义。例如，可以在描述 `price` 对象的 `definitions` 部分中创建称为 `Price` 的定义。`$ref` 的值是 `Price` 定义。

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStoreModelReUsableRef",
  "required" : ["price", "type" ],
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "type" : {
      "type" : "string",
      "enum" : [ "dog", "cat", "fish" ]
    },
    "price" : {
        "$ref": "#/definitions/Price"
    }
  },
  "definitions" : {
      "Price": {
        "type" : "number",
        "minimum" : 25.0,
        "maximum" : 500.0
            }
      }
}
```

您也可以引用在外部模型文件中定义的另一个模型架构。将 `$ref` 属性的值设置为模型的位置。在以下示例中，`Price` 模型是在 API `a1234` 的 `PetStorePrice` 模型中定义的。

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStorePrice",
  "type": "number",
  "minimum": 25,
  "maximum": 500
}
```

较长的模型可以引用 `PetStorePrice` 模型。

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStoreModelReusableRefAPI",
  "required" : [ "price", "type" ],
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "type" : {
      "type" : "string",
      "enum" : [ "dog", "cat", "fish" ]
    },
    "price" : {
        "$ref": "https://apigateway.amazonaws.com/restapis/a1234/models/PetStorePrice"
    }
  }
}
```

## 使用输出数据模型
<a name="api-gateway-request-validation-output-model"></a>

如果您转换数据，则可以在集成响应中定义负载模型。生成 SDK 时可以使用负载模型。对于强类型语言（如 Java、Objective-C 或 Swift），对象对应于用户定义的数据类型 (UDT)。如果您在生成 SDK 时向其提供数据模型，API Gateway 将创建 UDT。有关数据转换的更多信息，请参阅[API Gateway 中 REST API 的映射模板转换](models-mappings.md)。

以下示例是来自集成响应的输出数据。

```
{
[
  {
    "description" : "Item 1 is a dog.",
    "askingPrice" : 249.99
  },
  {
    "description" : "Item 2 is a cat.",
    "askingPrice" : 124.99
  },
  {
    "description" : "Item 3 is a fish.",
    "askingPrice" : 0.99
  }
]
}
```

以下示例是描述输出数据的负载模型。

```
{
"$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PetStoreOutputModel",
  "type" : "object",
  "required" : [ "description", "askingPrice" ],
  "properties" : {
    "description" : {
      "type" : "string"
    },
    "askingPrice" : {
      "type" : "number",
      "minimum" : 25.0,
      "maximum" : 500.0
    }
  }
}
```

借助此模型，您可以调用 SDK，以便通过读取 `PetStoreOutputModel[i].description` 和 `PetStoreOutputModel[i].askingPrice` 属性来检索 `description` 和 `askingPrice` 属性值。如果未提供模型，API Gateway 将使用空模型创建默认 UDT。

## 后续步骤
<a name="api-gateway-request-validation-model-next-steps"></a>
+ 本节提供的资源可用于获得有关本主题中介绍的概念的更多知识。

  您可以按照请求验证教程进行操作：
  + [使用 API Gateway 控制台设置请求验证](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-in-console)
  +  [使用 AWS CLI 设置基本请求验证](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-cli)
  +  [使用 OpenAPI 定义设置基本请求验证](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-importing-swagger)
+  有关数据转换和映射模板的更多信息，请参阅[API Gateway 中 REST API 的映射模板转换](models-mappings.md)。

# 在 API Gateway 中设置基本请求验证
<a name="api-gateway-request-validation-set-up"></a>

 本节介绍如何使用控制台、AWS CLI 和 OpenAPI 定义为 API Gateway 设置请求验证。

**Topics**
+ [使用 API Gateway 控制台设置请求验证](#api-gateway-request-validation-setup-in-console)
+ [使用 AWS CLI 设置基本请求验证](#api-gateway-request-validation-setup-cli)
+ [使用 OpenAPI 定义设置基本请求验证](#api-gateway-request-validation-setup-importing-swagger)

## 使用 API Gateway 控制台设置请求验证
<a name="api-gateway-request-validation-setup-in-console"></a>

 您可以使用 API Gateway 控制台从 API 请求的三个验证程序中选择一个来验证请求：
+ **验证正文**。
+ **验证查询字符串参数和标头**。
+ **验证正文、查询字符串参数和标头**。

 当您对 API 方法应用以上一种验证程序时，API Gateway 控制台会向 API 的 [RequestValidators](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html) 映射添加该验证程序。

要按本教程操作，您将使用 CloudFormation 模板来创建不完整的 API Gateway API。此 API 拥有的 `/validator` 资源具有 `GET` 和 `POST` 方法。两种方法都与 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点集成。您将配置两种请求验证：
+ 在 `GET` 方法中，您将为 URL 查询字符串参数配置请求验证。
+ 在 `POST` 方法中，您将为请求正文配置请求验证。

 这将只允许特定的 API 调用传递给 API。

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/request-validation-tutorial-console.zip)。您将使用此模板创建不完整的 API。您将在 API Gateway 控制台中完成其余步骤。

**创建 CloudFormation 堆栈**

1. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择**创建堆栈**，然后选择**使用新资源(标准)**。

1. 对于**指定模板**，选择**上传模板文件**。

1. 选择您下载的模板。

1. 选择**下一步**。

1. 对于**堆栈名称**，输入 **request-validation-tutorial-console**，然后选择**下一步**。

1. 对于**配置堆栈选项**，请选择**下一步**。

1. 对于**功能**，请确认 CloudFormation 可以在您的账户中创建 IAM 资源。

1. 选择**下一步**，然后选择**提交**。

CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。当 CloudFormation 堆栈的状态为 **CREATE\$1COMPLETE** 时，您就可以继续下一步了。

**选择您新创建的 API**

1. 选择新创建的 **request-validation-tutorial-console** 堆栈。

1. 选择**资源**。

1. 在**物理 ID** 下，选择您的 API。此链接将引导您进入 API Gateway 控制台。

在修改 `GET` 和 `POST` 方法之前，必须创建模型。

**创建模型**

1. 需要一个模型来对传入请求的正文使用请求验证。要创建模型，请在主导航窗格中选择**模型**。

1. 选择**创建模型**。

1. 对于**名称**，请输入 **PetStoreModel**。

1. 对于**内容类型**，输入 **application/json**。如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请输入 **\$1default**。

1. 对于**描述**，输入 **My PetStore Model** 作为模型描述。

1. 对于**模型架构**，将以下模型粘贴到代码编辑器中，然后选择**创建**。

   ```
   {
     "type" : "object",
     "required" : [ "name", "price", "type" ],
     "properties" : {
       "id" : {
         "type" : "integer"
       },
       "type" : {
         "type" : "string",
         "enum" : [ "dog", "cat", "fish" ]
       },
       "name" : {
         "type" : "string"
       },
       "price" : {
         "type" : "number",
         "minimum" : 25.0,
         "maximum" : 500.0
       }
     }
   }
   ```

有关模型的更多信息，请参阅[针对 REST API 的数据模型](models-mappings-models.md)。

**为 `GET` 方法配置请求验证**

1. 在主导航窗格中，选择**资源**，然后选择 **GET** 方法。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**请求验证程序**，选择**验证查询字符串参数和标头**。

1. 在 **URL 查询字符串参数**下，执行以下操作：

   1. 选择**添加查询字符串**。

   1. 在**名称**中，输入 **petType**。

   1. 打开**必需**。

   1. 将**缓存**保持为关闭状态。

1. 选择**保存**。

1. 在**集成请求**选项卡的**集成请求设置**下，选择**编辑**。

1. 在 **URL 查询字符串参数**下，执行以下操作：

   1. 选择**添加查询字符串**。

   1. 在**名称**中，输入 **petType**。

   1. 对于**映射自**，输入 **method.request.querystring.petType**。这会将 **petType** 映射到宠物的类型。

      有关数据映射的更多信息，请参阅[数据映射教程](set-up-data-transformations-in-api-gateway.md#mapping-example-console)。

   1. 将**缓存**保持为关闭状态。

1. 选择**保存**。

**为 `GET` 方法测试请求验证**

1. 选择**测试**选项卡。您可能需要选择右箭头按钮，以显示该选项卡。

1. 对于**查询字符串**，输入 **petType=dog**，然后选择**测试**。

1. 方法测试将返回 `200 OK` 并提供狗的列表。

   有关如何转换此输出数据的信息，请参阅[数据映射教程](set-up-data-transformations-in-api-gateway.md#mapping-example-console)。

1. 删除 **petType=dog** 并选择**测试**。

1.  方法测试将返回 `400` 错误并显示以下错误消息：

   ```
   {
     "message": "Missing required request parameters: [petType]"
   }
   ```

**为 `POST` 方法配置请求验证**

1. 在主导航窗格中，选择**资源**，然后选择 **POST** 方法。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**请求验证程序**，选择**验证正文**。

1. 在**请求正文**下，选择**添加模型**。

1. 对于**内容类型**，输入 **application/json**。如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请输入 `$default`。

    对于**模型**，请选择 **PetStoreModel**。

1. 选择**保存**。

**为 `POST` 方法测试请求验证**

1. 选择**测试**选项卡。您可能需要选择右箭头按钮，以显示该选项卡。

1. 对于**请求正文**，将以下内容粘贴到代码编辑器中：

   ```
   {
     "id": 2,
     "name": "Bella",
     "type": "dog",
     "price": 400
   }
   ```

    选择**测试**。

1. 方法测试将返回 `200 OK` 和成功消息。

1. 对于**请求正文**，将以下内容粘贴到代码编辑器中：

   ```
   {
     "id": 2,
     "name": "Bella",
     "type": "dog",
     "price": 4000
   }
   ```

    选择**测试**。

1.  方法测试将返回 `400` 错误并显示以下错误消息：

   ```
   {
    "message": "Invalid request body"
   }
   ```

    在测试日志的底部，将返回请求正文无效的原因。在这种情况下，宠物的价格超出了模型中规定的最高价格。

**删除 CloudFormation 堆栈**

1. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择您的 CloudFormation 堆栈。

1. 选择**删除**，然后确认您的选择。

### 后续步骤
<a name="next-steps-request-validation-tutorial"></a>
+ 有关如何转换输出数据和执行更多数据映射的信息，请参阅[数据映射教程](set-up-data-transformations-in-api-gateway.md#mapping-example-console)。
+ 按照[使用 AWS CLI 设置基本请求验证](#api-gateway-request-validation-setup-cli)教程操作，使用 AWS CLI 执行类似的步骤。

## 使用 AWS CLI 设置基本请求验证
<a name="api-gateway-request-validation-setup-cli"></a>

您可以使用 AWS CLI 创建验证程序来设置请求验证。要按本教程操作，您将使用 CloudFormation 模板来创建不完整的 API Gateway API。

**注意**  
这与控制台教程的 CloudFormation 模板不同。

 使用预先公开的 `/validator` 资源，您将创建 `GET` 和 `POST` 方法。两种方法都将与 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 端点集成。您将配置以下两个请求验证：
+ 在 `GET` 方法上，您将创建一个 `params-only` 验证程序来验证 URL 查询字符串参数。
+ 在 `POST` 方法上，您将创建一个 `body-only` 验证程序来验证请求正文。

 这将只允许特定的 API 调用传递给 API。

**创建 CloudFormation 堆栈**

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/request-validation-tutorial-cli.zip)。

要完成以下教程，您需要 [AWS Command Line Interface（AWS CLI）版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

对于长命令，使用转义字符 (`\`) 将命令拆分为多行。
**注意**  
在 Windows 中，操作系统的内置终端不支持您经常使用的某些 Bash CLI 命令（例如 `zip`）。[安装 Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install)，获取 Ubuntu 和 Bash 与 Windows 集成的版本。本指南中的示例 CLI 命令使用 Linux 格式。如果您使用的是 Windows CLI，则必须重新格式化包含内联 JSON 文档的命令。

1.  输入以下命令创建 CloudFormation 堆栈。

   ```
   aws cloudformation create-stack --stack-name request-validation-tutorial-cli --template-body file://request-validation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。使用以下命令查看 CloudFormation 的状态。

   ```
   aws cloudformation describe-stacks --stack-name request-validation-tutorial-cli
   ```

1. 当 CloudFormation 堆栈的状态为 `StackStatus: "CREATE_COMPLETE"` 时，使用以下命令检索将来步骤的相关输出值。

   ```
    aws cloudformation describe-stacks --stack-name request-validation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   输出值包括：
   + ApiId，这是 API 的 ID。对于本教程，API ID 为 `abc123`。
   + ResourceId，这是在其中公开 `GET` 和 `POST` 方法的验证程序资源的 ID。对于本教程，资源 ID 为 `efg456`

**创建请求验证程序并导入模型**

1. 需要验证程序才能通过 AWS CLI 使用请求验证。使用以下命令创建仅验证请求参数的验证程序。

   ```
   aws apigateway create-request-validator --rest-api-id abc123 \
         --no-validate-request-body \
         --validate-request-parameters \
         --name params-only
   ```

   记下 `params-only` 验证程序的 ID。

1.  使用以下命令创建仅验证请求正文的验证程序。

   ```
   aws apigateway create-request-validator --rest-api-id abc123 \
         --validate-request-body \
         --no-validate-request-parameters \
         --name body-only
   ```

   记下 `body-only` 验证程序的 ID。

1.  需要一个模型来对传入请求的正文使用请求验证。使用以下命令导入模型。

   ```
   aws apigateway create-model --rest-api-id abc123 --name PetStoreModel --description 'My PetStore Model' --content-type 'application/json' --schema '{"type": "object", "required" : [ "name", "price", "type" ], "properties" : { "id" : {"type" : "integer"},"type" : {"type" : "string", "enum" : [ "dog", "cat", "fish" ]},"name" : { "type" : "string"},"price" : {"type" : "number","minimum" : 25.0, "maximum" : 500.0}}}}' 
   ```

   如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请指定 `$default` 作为键。

**创建 `GET` 和 `POST` 方法**

1. 使用以下命令对 `/validate` 资源添加 `GET` HTTP 方法。此命令创建 `GET` 方法，添加 `params-only` 验证程序，并根据需要设置查询字符串 `petType`。

   ```
   aws apigateway put-method --rest-api-id abc123 \
          --resource-id efg456 \
          --http-method GET \
          --authorization-type "NONE" \
          --request-validator-id aaa111 \
          --request-parameters "method.request.querystring.petType=true"
   ```

   使用以下命令对 `/validate` 资源添加 `POST` HTTP 方法。此命令创建 `POST` 方法，添加 `body-only` 验证程序，并将模型附加到仅限正文的验证程序。

   ```
   aws apigateway put-method --rest-api-id abc123 \
          --resource-id efg456 \
          --http-method POST \
          --authorization-type "NONE" \
          --request-validator-id bbb222 \
          --request-models 'application/json'=PetStoreModel
   ```

1.  使用以下命令设置 `GET /validate` 方法的 `200 OK` 响应。

   ```
   aws apigateway put-method-response --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method GET \
               --status-code 200
   ```

    使用以下命令设置 `POST /validate` 方法的 `200 OK` 响应。

   ```
   aws apigateway put-method-response --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method POST \
               --status-code 200
   ```

1.  使用以下命令通过指定的 HTTP 端点为 `GET /validation` 方法设置 `Integration`。

   ```
   aws apigateway put-integration --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method GET \
               --type HTTP \
               --integration-http-method GET \
               --request-parameters '{"integration.request.querystring.type" : "method.request.querystring.petType"}' \
               --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   ```

    使用以下命令通过指定的 HTTP 端点为 `POST /validation` 方法设置 `Integration`。

   ```
   aws apigateway put-integration --rest-api-id abc123  \
                 --resource-id efg456 \
                 --http-method POST \
                 --type HTTP \
                 --integration-http-method GET \
                 --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   ```

1.  使用以下命令设置 `GET /validation` 方法的集成响应。

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
                 --resource-id efg456\
                 --http-method GET \
                 --status-code 200 \
                 --selection-pattern ""
   ```

    使用以下命令设置 `POST /validation` 方法的集成响应。

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method POST \
               --status-code 200 \
               --selection-pattern ""
   ```

**测试 API**

1. 要测试将对查询字符串执行请求验证的 `GET` 方法，请使用以下命令：

   ```
   aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method GET \
               --path-with-query-string '/validate?petType=dog'
   ```

   结果将返回 `200 OK` 和狗的列表。

1. 使用以下命令在不包含查询字符串 `petType` 的情况下进行测试

   ```
   aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method GET
   ```

   结果将返回 `400` 错误。

1. 要测试将对请求正文执行请求验证的 `POST` 方法，请使用以下命令：

   ```
    aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method POST \
               --body '{"id": 1, "name": "bella", "type": "dog", "price" : 400 }'
   ```

   结果将返回 `200 OK` 和一条成功消息。

1. 使用以下命令通过无效的正文进行测试。

   ```
    aws apigateway test-invoke-method --rest-api-id abc123 \
                 --resource-id efg456 \
                 --http-method POST \
                 --body '{"id": 1, "name": "bella", "type": "dog", "price" : 1000 }'
   ```

   结果将返回 `400` 错误，因为狗的价格超过了模型定义的最高价格。

**删除 CloudFormation 堆栈**
+ 使用以下命令删除您的 CloudFormation 资源。

  ```
  aws cloudformation delete-stack  --stack-name request-validation-tutorial-cli
  ```

## 使用 OpenAPI 定义设置基本请求验证
<a name="api-gateway-request-validation-setup-importing-swagger"></a>

 您可以在 API 级别声明请求验证程序，方法是在 [x-amazon-apigateway-request-validators 对象](api-gateway-swagger-extensions-request-validators.md) 映射中指定一组 [x-amazon-apigateway-request-validators.requestValidator 对象](api-gateway-swagger-extensions-request-validators.requestValidator.md) 对象，以选择将对请求的哪个部分进行验证。在示例 OpenAPI 定义中，有两个验证程序：
+ `all` 验证程序，它验证正文（使用 `RequestBodyModel` 数据模型）和参数。

  `RequestBodyModel` 数据模型要求输入 JSON 对象包含 `name`、`type` 和 `price` 属性。`name` 属性可以是任何字符串，`type` 必须是一种指定枚举字段 (`["dog", "cat", "fish"]`)，而 `price` 必须介于 25 和 500 之间。`id` 参数不是必需参数。
+ `param-only`，它只验证参数。

 要在 API 的所有方法上开启请求验证程序，请在 API 级别指定 OpenAPI 定义的 [x-amazon-apigateway-request-validator 属性](api-gateway-swagger-extensions-request-validator.md) 属性。在示例 OpenAPI 定义中，`all` 验证器用于所有 API 方法，除非被覆盖。使用模型验证正文时，如果找不到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请指定 `$default` 作为键。

要针对单独的方法开启请求验证程序，请在方法级别指定 `x-amazon-apigateway-request-validator` 属性。在示例 OpenAPI 定义中，`param-only` 验证程序会覆盖 `GET` 方法上的 `all` 验证程序。



要将 OpenAPI 示例导入 API Gateway，请参阅以下有关[将区域 API 导入到 API Gateway 中](import-export-api-endpoints.md)或[将边缘优化的 API 导入 API Gateway](import-edge-optimized-api.md)的说明。

------
#### [ OpenAPI 3.0 ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "ReqValidators Sample",
    "version" : "1.0.0"
  },
  "servers" : [ {
    "url" : "/{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "/v1"
      }
    }
  } ],
  "paths" : {
    "/validation" : {
      "get" : {
        "parameters" : [ {
          "name" : "q1",
          "in" : "query",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "test-method-response-header" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ArrayOfError"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "params-only",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.type" : "method.request.querystring.q1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      },
      "post" : {
        "parameters" : [ {
          "name" : "h1",
          "in" : "header",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RequestBodyModel"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "test-method-response-header" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ArrayOfError"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "all",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "POST",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.custom_h1" : "method.request.header.h1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "RequestBodyModel" : {
        "required" : [ "name", "price", "type" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string",
            "enum" : [ "dog", "cat", "fish" ]
          },
          "name" : {
            "type" : "string"
          },
          "price" : {
            "maximum" : 500.0,
            "minimum" : 25.0,
            "type" : "number"
          }
        }
      },
      "ArrayOfError" : {
        "type" : "array",
        "items" : {
          "$ref" : "#/components/schemas/Error"
        }
      },
      "Error" : {
        "type" : "object"
      }
    }
  },
  "x-amazon-apigateway-request-validators" : {
    "all" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : true
    },
    "params-only" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : false
    }
  }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger" : "2.0",
  "info" : {
    "version" : "1.0.0",
    "title" : "ReqValidators Sample"
  },
  "basePath" : "/v1",
  "schemes" : [ "https" ],
  "paths" : {
    "/validation" : {
      "get" : {
        "produces" : [ "application/json", "application/xml" ],
        "parameters" : [ {
          "name" : "q1",
          "in" : "query",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/ArrayOfError"
            },
            "headers" : {
              "test-method-response-header" : {
                "type" : "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "params-only",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.type" : "method.request.querystring.q1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      },
      "post" : {
        "consumes" : [ "application/json" ],
        "produces" : [ "application/json", "application/xml" ],
        "parameters" : [ {
          "name" : "h1",
          "in" : "header",
          "required" : true,
          "type" : "string"
        }, {
          "in" : "body",
          "name" : "RequestBodyModel",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/RequestBodyModel"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/ArrayOfError"
            },
            "headers" : {
              "test-method-response-header" : {
                "type" : "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "all",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "POST",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.custom_h1" : "method.request.header.h1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "definitions" : {
    "RequestBodyModel" : {
      "type" : "object",
      "required" : [ "name", "price", "type" ],
      "properties" : {
        "id" : {
          "type" : "integer"
        },
        "type" : {
          "type" : "string",
          "enum" : [ "dog", "cat", "fish" ]
        },
        "name" : {
          "type" : "string"
        },
        "price" : {
          "type" : "number",
          "minimum" : 25.0,
          "maximum" : 500.0
        }
      }
    },
    "ArrayOfError" : {
      "type" : "array",
      "items" : {
        "$ref" : "#/definitions/Error"
      }
    },
    "Error" : {
      "type" : "object"
    }
  },
  "x-amazon-apigateway-request-validators" : {
    "all" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : true
    },
    "params-only" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : false
    }
  }
}
```

------

# AWS CloudFormation 模板，提供带有基本请求验证的示例 API
<a name="api-gateway-request-validation-sample-cloudformation"></a>

 以下 CloudFormation 示例模板定义一个启用了请求验证的示例 API。该 API 是 [PetStore API](http://petstore-demo-endpoint.execute-api.com/petstore/pets) 的一部分。其使用 `POST` 方法将宠物添加到 `pets` 集合，并使用 `GET` 方法按指定类型查询宠物。

 其中声明了两个请求验证程序：

**`GETValidator`**  
此验证程序已在 `GET` 方法上启用。它允许 API Gateway 验证所需的查询参数 (`q1`) 是否包含在传入请求内且不为空。

**`POSTValidator`**  
此验证程序已在 `POST` 方法上启用。它允许 API Gateway 在内容类型为 `application/json` 时，验证负载请求格式是否遵循指定的 `RequestBodyModel`，如果未找到匹配的内容类型，则不执行请求验证。要使用同一模型而不考虑内容类型，请指定`$default`。`RequestBodyModel` 包含一个额外的模型 `RequestBodyModelId`，用于定义宠物 ID。

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: ReqValidatorsSample
  RequestBodyModelId:
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref Api
      ContentType: application/json
      Description: Request body model for Pet ID.
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: RequestBodyModelId
        properties:
            id:
              type: integer
  RequestBodyModel: 
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref Api
      ContentType: application/json
      Description: Request body model for Pet type, name, price, and ID.
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: RequestBodyModel
        required:
          - price
          - name
          - type
        type: object
        properties:
            id:
              "$ref": !Sub 
                - 'https://apigateway.amazonaws.com/restapis/${Api}/models/${RequestBodyModelId}'
                - Api: !Ref Api
                  RequestBodyModelId: !Ref RequestBodyModelId
            price: 
              type: number
              minimum: 25
              maximum: 500
            name:
              type: string
            type:
              type: string
              enum:
                - "dog"
                - "cat"
                - "fish"
  GETValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: params-only
      RestApiId: !Ref Api
      ValidateRequestBody: False
      ValidateRequestParameters: True 
  POSTValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: body-only
      RestApiId: !Ref Api
      ValidateRequestBody: True
      ValidateRequestParameters: False
  ValidationResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'validation'
  ValidationMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref ValidationResource
      HttpMethod: GET
      AuthorizationType: NONE
      RequestValidatorId: !Ref GETValidator
      RequestParameters:
        method.request.querystring.q1: true
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ValidationMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref ValidationResource
      HttpMethod: POST
      AuthorizationType: NONE
      RequestValidatorId: !Ref POSTValidator
      RequestModels:
        application/json : !Ref RequestBodyModel 
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: POST
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - ValidationMethodGet
      - RequestBodyModel 
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiRootUrl:
    Description: Root Url of the API
    Value: !Sub 'https://${Api}.execute-api.${AWS::Region}.amazonaws.com/${StageName}'
```