

# 在 API Gateway 中使用 OpenAPI 开发 REST API
<a name="api-gateway-import-api"></a>

您可以使用 API Gateway 将 REST API 从外部定义文件导入到 API Gateway。目前，API Gateway 支持 [OpenAPI v2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) 和 [OpenAPI v3.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.1.md) 定义文件，但[Amazon API Gateway 关于 REST API 的重要说明](api-gateway-known-issues.md#api-gateway-known-issues-rest-apis)中列出了例外。您可以使用新定义覆盖 API 以进行更新，还可以将定义与现有 API 合并。您使用 `mode` 查询参数指定请求 URL 中的选项。

有关从 API Gateway 控制台使用导入 API 功能的教程，请参阅 [教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

**Topics**
+ [将边缘优化的 API 导入 API Gateway](import-edge-optimized-api.md)
+ [将区域 API 导入到 API Gateway 中](import-export-api-endpoints.md)
+ [导入 OpenAPI 文件以更新现有 API 定义](api-gateway-import-api-update.md)
+ [设置 OpenAPI `basePath` 属性](api-gateway-import-api-basePath.md)
+ [用于 OpenAPI 导入的 AWS 变量](import-api-aws-variables.md)
+ [将 API 导入 API Gateway 时出现的错误和警告](api-gateway-import-api-errors-warnings.md)
+ [从 API Gateway 导出 REST API](api-gateway-export-api.md)

# 将边缘优化的 API 导入 API Gateway
<a name="import-edge-optimized-api"></a>

您可以导入 API 的 OpenAPI 定义文件，在 OpenAPI 文件之外通过指定 `EDGE` 端点类型作为导入操作的附加输入，创建新的边缘优化的 API。您可以使用 API Gateway 控制台、AWS CLI 或 AWS SDK 执行此操作。

有关从 API Gateway 控制台使用导入 API 特征的教程，请参阅 [教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

**Topics**
+ [使用 API Gateway 控制台导入边缘优化的 API](#import-edge-optimized-api-with-console)
+ [使用 AWS CLI 导入边缘优化的 API](#import-edge-optimized-api-with-awscli)

## 使用 API Gateway 控制台导入边缘优化的 API
<a name="import-edge-optimized-api-with-console"></a>

要使用 API Gateway 控制台导入边缘优化的 API，请执行以下操作：

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择**创建 API**。

1. 在**REST API**中，选择 **Import**（导入）。

1.  复制 API 的 OpenAPI 定义并将其粘贴到代码编辑器中，或者选择**选择文件**以从本地驱动器加载 OpenAPI 文件。

1.  对于 **API 端点类型**，选择**边缘优化**。

1.  选择**创建 API** 以开始导入 OpenAPI 定义。

## 使用 AWS CLI 导入边缘优化的 API
<a name="import-edge-optimized-api-with-awscli"></a>

以下 [import-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html) 命令从 OpenAPI 定义文件导入 API，以创建边缘优化的新 API：

```
aws apigateway import-rest-api \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```

或者使用到 `EDGE` 的 `endpointConfigurationTypes` 查询字符串参数的明确规范：

```
aws apigateway import-rest-api \
    --parameters endpointConfigurationTypes=EDGE \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```



# 将区域 API 导入到 API Gateway 中
<a name="import-export-api-endpoints"></a>

导入 API 时，您可以为 API 选择区域端点配置。您可以使用 API Gateway 控制台、AWS CLI 或 AWS SDK。

导出 API 时，API 端点配置不包括在导出的 API 定义中。

有关从 API Gateway 控制台使用导入 API 特征的教程，请参阅 [教程：通过导入示例创建 REST API](api-gateway-create-api-from-example.md)。

**Topics**
+ [使用 API Gateway 控制台导入区域 API](#import-regional-api-with-console)
+ [使用 AWS CLI 导入区域 API](#import-regional-api-with-awscli)

## 使用 API Gateway 控制台导入区域 API
<a name="import-regional-api-with-console"></a>

要使用 API Gateway 控制台导入区域端点的 API，请执行以下操作：

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择**创建 API**。

1. 在**REST API**中，选择 **Import**（导入）。

1.  复制 API 的 OpenAPI 定义并将其粘贴到代码编辑器中，或者选择**选择文件**以从本地驱动器加载 OpenAPI 文件。

1. 对于 **API 端点类型**，选择**区域**。

1.  选择**创建 API** 以开始导入 OpenAPI 定义。

## 使用 AWS CLI 导入区域 API
<a name="import-regional-api-with-awscli"></a>

使用以下 [import-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html) 命令导入 OpenAPI 定义文件，并将端点类型设置为“区域”：

```
aws apigateway import-rest-api \
    --parameters endpointConfigurationTypes=REGIONAL \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```

# 导入 OpenAPI 文件以更新现有 API 定义
<a name="api-gateway-import-api-update"></a>

 您只能导入 API 定义来更新现有 API，无需更改其终端节点配置以及阶段或阶段变量，或者引用 API 密钥。

 导入到更新操作可以使用两种模式进行：合并和覆盖。

当一个 API (`A`) 合并到另一个 (`B`) 中时，如果两个 API 中没有互相冲突的定义，生成的 API 会保留 `A` 和 `B` 两者的定义。如果出现冲突，合并 API (`A`) 的方法定义会覆盖接受并入的 API (`B`) 的相应方法定义。例如，假设 `B` 声明了以下方法，用于返回 `200` 和 `206` 响应：

```
GET /a
POST /a
```

`A` 声明了以下方法，用于返回 `200` 和 `400` 响应：

```
GET /a
```

如果 `A` 并入 `B` 中，生成的 API 会生成以下方法：

```
GET /a
```

返回 `200` 和 `400` 响应，以及 

```
POST /a
```

返回 `200` 和 `206` 响应。

当您将外部 API 定义分解为多个较小的部分，并希望一次只应用其中一个部分的更改时，合并 API 非常有用。例如，如果多个团队负责一个 API 的不同部分并以不同的速度提供更改，则可能会出现此情况。在这种模式下，没有在导入的定义中明确定义的现有 API 中的项目会被忽略。

如果一个 API (`A`) 覆盖另一个 API (`B`)，生成的 API 将采纳覆盖方 API (`A`) 的定义。当外部 API 定义包含一个 API 的完整定义时，覆盖 API 非常有用。在这种模式下，没有在导入的定义中明确定义的现有 API 中的项目会被删除。

 要合并 API，请将一个 `PUT` 请求提交至 `https://apigateway.<region>.amazonaws.com/restapis/<restapi_id>?mode=merge`。`restapi_id` 路径参数值指定了将要与提供的 API 定义合并的 API。

 以下代码段显示了一个 `PUT` 请求的示例，该请求将作为负载的 JSON 格式的 OpenAPI API 定义与 API Gateway 中已指定的 API 合并。

```
PUT /restapis/<restapi_id>?mode=merge
Host:apigateway.<region>.amazonaws.com
Content-Type: application/json
Content-Length: ...

An OpenAPI API definition in JSON
```

 合并更新操作需要提取两个完整的 API 定义并将它们合并到一起。对于小型增量变更，您可以使用[资源更新](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateResource.html)操作。

 要覆盖 API，请将一个 `PUT` 请求提交至 `https://apigateway.<region>.amazonaws.com/restapis/<restapi_id>?mode=overwrite`。`restapi_id` 路径参数指定了将要被提供的 API 定义覆盖的 API。

 以下代码段显示了一个覆盖请求的示例，该请求的负载为 JSON 格式 OpenAPI 定义：

```
PUT /restapis/<restapi_id>?mode=overwrite
Host:apigateway.<region>.amazonaws.com
Content-Type: application/json
Content-Length: ...

An OpenAPI API definition in JSON
```

 如果未指定 `mode` 查询参数，则系统会假定合并。

**注意**  
 `PUT` 操作是幂等操作，不是原子操作。这意味着如果在处理过程中出现系统错误，则 API 可能会以不良状态结束。但是，重复该操作会成功将 API 置于相同的最终状态，如同第一次操作已成功一样。

# 设置 OpenAPI `basePath` 属性
<a name="api-gateway-import-api-basePath"></a>

在 [OpenAPI 2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) 中，您可以使用 `basePath` 属性来提供 `paths` 属性中定义的每个路径之前的一个或多个路径部分。由于 API Gateway 具有多种表达资源路径的方式，因此导入 API 功能可提供以下选项用于解释导入过程中的 `basePath` 属性：ignore、prepend 和 split。

在 [https://swagger.io/docs/specification/api-host-and-base-path/](https://swagger.io/docs/specification/api-host-and-base-path/) 中，`basePath` 不再是顶级属性。相反，作为惯例，API Gateway 使用[服务器变量](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#serverVariableObject)。导入 API 功能提供了相同选项用于解释导入过程中的基本路径。按如下所示标识基本路径：
+ 如果 API 不包含任何 `basePath` 变量，则导入 API 功能将检查 `server.url` 字符串以查看其是否包含 `"/"` 之外的路径。如果包含，则将该路径用作基本路径。
+ 如果 API 仅包含一个 `basePath` 变量，则导入 API 功能将使用其作为基本路径，即使该变量未在 `server.url` 中进行引用。
+ 如果 API 包含多个 `basePath` 变量，则导入 API 功能将仅使用第一个变量作为基本路径。

## 忽略
<a name="api-gateway-import-api-basePath-ignore"></a>

如果 OpenAPI 文件的 `basePath` 值为 `/a/b/c` 且 `paths` 属性包含 `/e` 和 `/f`，则以下 `POST` 或 `PUT` 请求：

```
POST /restapis?mode=import&basepath=ignore
```



```
PUT /restapis/api_id?basepath=ignore
```

 将在 API 中生成以下资源：
+ `/`
+ `/e`
+ `/f`

 效果是将 `basePath` 视为不存在，所有声明的 API 资源均相对于主机提供。例如，如果您有一个自定义域名，其 API 映射不包含*基础路径*和表示生产阶段的*阶段*值，则可以使用这一选项。

**注意**  
 API Gateway 自动为您创建一个根资源，即使该资源未在定义文件中明确声明。

 如未指定，`basePath` 以 `ignore` 为默认值。

## 前置
<a name="api-gateway-import-api-basePath-prepend"></a>

 如果 OpenAPI 文件的 `basePath` 值为 `/a/b/c` 且 `paths` 属性包含 `/e` 和 `/f`，则以下 `POST` 或 `PUT` 请求：

```
POST /restapis?mode=import&basepath=prepend
```



```
PUT /restapis/api_id?basepath=prepend
```

 将在 API 中生成以下资源：
+ `/`
+ `/a`
+ `/a/b`
+ `/a/b/c`
+ `/a/b/c/e`
+ `/a/b/c/f`

 效果是将 `basePath` 视为指定其他资源 (不含方法) 并将这些资源添加到声明的资源组中。例如，如果不同的团队负责一个 API 的不同部分且 `basePath` 可以为每个团队所负责 API 部分引用路径位置，则可以使用这一选项。

**注意**  
 API Gateway 自动为您创建中间资源，即使这些资源未在定义中明确声明。

## Split
<a name="api-gateway-import-api-basePath-split"></a>

 如果 OpenAPI 文件的 `basePath` 值为 `/a/b/c` 且 `paths` 属性包含 `/e` 和 `/f`，则以下 `POST` 或 `PUT` 请求：

```
POST /restapis?mode=import&basepath=split
```



```
PUT /restapis/api_id?basepath=split
```

 将在 API 中生成以下资源：
+ `/`
+ `/b`
+ `/b/c`
+ `/b/c/e`
+ `/b/c/f`

 效果是将最顶层的路径部分 `/a` 视为每个资源路径的开始，并在 API 自身内创建其他资源 (不含方法)。例如，如果 `a` 是一个您想在 API 中使用的阶段名称，则可以使用这一选项。

# 用于 OpenAPI 导入的 AWS 变量
<a name="import-api-aws-variables"></a>

您可以在 OpenAPI 定义中使用以下 AWS 变量。API Gateway 在导入 API 时解析变量。要指定变量，请使用 `${variable-name}`。下表介绍了可用的 AWS 变量。


| 变量名称 | 描述 | 
| --- | --- | 
| AWS::AccountId | 导入 API 的 AWS 账户 ID。例如，123456789012。 | 
| AWS::Partition | 在其中导入 API 的 AWS 分区。对于标准 AWS 区域，分区是 aws。 | 
| AWS::Region | 在其中导入 API 的 AWS 区域。例如，us-east-2。 | 

## AWS 变量示例
<a name="import-api-aws-variables-example"></a>

以下示例使用 AWS 变量为集成指定 AWS Lambda 函数。

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

```
openapi: "3.0.1"
info:
  title: "tasks-api"
  version: "v1.0"
paths:
  /:
    get:
      summary: List tasks
      description: Returns a list of tasks
      responses:
        200:
          description: "OK"
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Task"
        500:
          description: "Internal Server Error"
          content: {}
      x-amazon-apigateway-integration:
        uri:
          arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaFunctionName/invocations
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"
components:
  schemas:
    Task:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
```

------

# 将 API 导入 API Gateway 时出现的错误和警告
<a name="api-gateway-import-api-errors-warnings"></a>

在将外部定义文件导入 API Gateway 时，API Gateway 可能会生成警告和错误。以下部分讨论导入过程中可能出现的错误和警告。

## 导入过程中出现错误
<a name="api-gateway-import-api-errors"></a>

 在导入过程中，可能会因 OpenAPI 文档无效等严重问题而产生错误。系统会在不成功响应中将错误作为异常（如 `BadRequestException`）返回。出现错误时，新的 API 定义会被丢弃，现有 API 不会发生更改。

## 导入过程中出现警告
<a name="api-gateway-import-api-warnings"></a>

 在导入过程中，可能会因缺失模型引用等轻微问题而产生警告。出现警告时，如果请求 URL 中附加了 `failonwarnings=false` 查询表达式，则操作将会继续。否则更新就会回滚。默认情况下，将 `failonwarnings` 设置为 `false`。在这种情况下，系统会在生成的 [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) 资源中以字段形式返回警告。否则，系统会将警告作为异常中的一条消息返回。

# 从 API Gateway 导出 REST API
<a name="api-gateway-export-api"></a>

 使用 API Gateway 控制台或其他方式在 API Gateway 中创建和配置 REST API 后，您可以使用 API Gateway 导出 API（该 API 是 Amazon API Gateway 控制服务的一部分）将其导出到 OpenAPI 文件。要使用 API Gateway 导出 API，您需要签署您的 API 请求。有关签署请求的更多信息，请参阅《IAM 用户指南》**中的[签署 AWS API 请求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)。您可以在导出的 OpenAPI 定义文件中包含 API Gateway 集成扩展以及 [Postman](https://www.postman.com) 扩展。

**注意**  
使用 AWS CLI 导出 API 时，请务必包含扩展参数，如以下示例所示，以确保包含 `x-amazon-apigateway-request-validator` 扩展：  

```
aws apigateway get-export --parameters extensions='apigateway' --rest-api-id abcdefg123 --stage-name dev --export-type swagger latestswagger2.json
```

 如果 API 的负载并非 `application/json` 类型，则您无法将其导出。如果尝试导出，您将收到一条错误响应，指出未找到 JSON 正文模型。

## 请求导出 REST API
<a name="api-gateway-export-api-request"></a>

 借助 Export API，您可以提交 GET 请求，将要导出的 REST 指定为 URL 路径的一部分，以此来导出现有 REST API。请求 URL 的格式如下：

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

```
 https://<host>/restapis/<restapi_id>/stages/<stage_name>/exports/oas30
```

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

```
 https://<host>/restapis/<restapi_id>/stages/<stage_name>/exports/swagger
```

------

 您可以附加 `extensions` 查询字符串，以指定是否要包含 API Gateway 扩展（含 `integration` 值）或 Postman 扩展（含 `postman` 值）。

 此外，您还可以将 `Accept` 标头设置为 `application/json` 或 `application/yaml`，以分别接收 JSON 格式或 YAML 格式的 API 定义输出。

 有关使用 API Gateway 导出 API 提交 GET 请求的更多信息，请参阅 [GetExport](https://docs.aws.amazon.com/apigateway/latest/api/API_GetExport.html)。

**注意**  
 如果您在 API 中定义模型，那么这些模型的内容类型必须为“application/json”，这样 API Gateway 才能将其导出。否则，API Gateway 会引发异常，并显示“仅找到适用于……的非 JSON 正文模型”的错误消息。  
 模型必须包含属性或者被定义为特定 JSONSchema 类型。

## 下载 JSON 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-json"></a>

要下载 JSON 格式的 REST API OpenAPI 定义，请执行以下操作：

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------

 这里的 `<region>` 可以是 (比如说) `us-east-1`。有关提供 API Gateway 的所有区域，请参阅 [Regions and Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#apigateway_region)。

## 下载 YAML 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-yaml"></a>

要下载 YAML 格式的 REST API OpenAPI 定义，请执行以下操作：

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------

## 借助 Postman 扩展下载 JSON 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-json-with-postman"></a>

借助 Postman 导出并下载 JSON 格式的 REST API OpenAPI 定义，请执行以下操作：

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30?extensions=postman
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger?extensions=postman
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------

## 借助 API Gateway 集成下载 YAML 格式的 REST API OpenAPI 定义
<a name="api-gateway-export-api-download-swagger-yaml-with-apig"></a>

要借助 API Gateway 集成导出并下载 YAML 格式的 REST API OpenAPI 定义，请执行以下操作：

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30?extensions=integrations
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

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

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger?extensions=integrations
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------

## 使用 API Gateway 控制台导出 REST API
<a name="api-gateway-export-api-from-console"></a>

[将 REST API 部署到一个阶段](set-up-deployments.md#create-deployment)之后，您可以使用 API Gateway 控制台将此阶段中的 API 导出到 OpenAPI 文件。

 在 API Gateway 控制台的**阶段**窗格中，选择**阶段操作**，然后选择**导出**。

![\[使用 API Gateway 控制台导出 REST API\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/export-new-console.png)


指定 **API 规范类型**、**格式**和**扩展**以下载您 API 的 OpenAPI 定义。