# OpenAPI 规范

> Source: https://strapi.nodejs.cn/cms/api/openapi

🌐 OpenAPI specification generation

Strapi 提供了一个 CLI 工具，用于自动生成 OpenAPI 3.1.0 规范，记录所有 API 端点、参数和响应。生成的规范可以与 Swagger UI 集成，用于交互式 API 文档。

🌐 Strapi provides a CLI tool to automatically generate OpenAPI 3.1.0 specifications documenting all API endpoints, parameters, and responses. The generated specification can be integrated with Swagger UI for interactive API documentation.

Strapi 提供了一个命令行工具来为你的应用生成 [OpenAPI](https://www.openapis.org/) 规范。 

CLI 工具会自动创建全面的 API 文档，描述你 Strapi 应用的内容 API 中所有可用的端点、参数和响应格式。在可能的使用场景中，生成的规范可以集成到像  [Swagger UI ](https://swagger.io/tools/swagger-ui/) 这样的文档工具中。

:::callout 🚧  Experimental feature

OpenAPI 生成特性目前处于实验阶段。其行为和输出在未来版本中可能会发生变化，且不遵循语义化版本控制。如需更多信息和背景，请参阅 [Strapi Contributor Docs ](https://contributor.strapi.io/openapi)。

:::

## 生成 OpenAPI 规范 {#generating-an-openapi-specification}

🌐 Generating an OpenAPI specification

OpenAPI 生成工具包含在 Strapi 核心中，无需额外安装。你可以在任何 Strapi 项目中直接从命令行使用它来生成全面的 API 文档。

🌐 The OpenAPI generation tool is included with Strapi core and doesn't require additional installation. You can use it directly from the command line in any Strapi project to generate comprehensive API documentation.

:::note Known limitation for nested component `required` metadata

管理面板可以将组件中的内部字段标记为必填，但生成的 OpenAPI 文件仍可能跳过这些标量的 `required` 条目。父对象（例如动态区域内的组件）可能列出 `required`，而嵌套属性则没有。在 [GitHub issue #2236](https://github.com/strapi/documentation/issues/2236) 中有更多背景信息。因此，仅信任原始模式的客户端生成器可能会生成看起来比 Strapi 实际执行更宽松的类型。

🌐 The Admin panel can mark inner fields on a component as required, yet the generated OpenAPI file may still skip a `required` entry for those scalars. The parent object (for instance a component inside a dynamic zone) might list `required` while the nested properties do not. There is more background in [GitHub issue #2236](https://github.com/strapi/documentation/issues/2236). Client generators that trust the raw schema alone can therefore emit types that look looser than what Strapi actually enforces.

此区域仍处于实验阶段，与页面顶部的警告横幅相同，因此请继续在应用代码中或使用控制器指南中的 [REST 验证助手](/cms/backend-customization/controllers#sanitization-and-validation-in-controllers) 验证嵌套负载，而不要假设每条管理员规则都已反映在导出的 JSON 模式中。

🌐 This area is still experimental, same as the warning banner at the top of the page, so keep validating nested payloads in application code or with the [REST validation helpers](/cms/backend-customization/controllers#sanitization-and-validation-in-controllers) from the controllers guide instead of assuming every Admin rule is mirrored in the exported JSON schema yet.

:::

### 命令行接口使用 {#cli-usage}

🌐 CLI usage

在不带任何参数的情况下执行该命令将在你的 Strapi 项目文件夹根目录下生成一个 `specification.json` 文件：

🌐 Executing the command without any arguments will generate a `specification.json` file at the root of your Strapi folder project:

```shell
yarn strapi openapi generate
```

```shell
npm run strapi openapi generate
```

你还可以传递一个可选的 `--output` 参数来指定路径和文件名，如下面的示例所示：

🌐 You can also pass an optional `--output` argument to specify the path and filename, as in the following example:

```bash
yarn strapi openapi generate --output ./docs/api-spec.json
```

```bash
npm run strapi openapi generate -- --output ./docs/api-spec.json
```

### 规范结构和内容 {#specification-structure-and-content}

🌐 Specification structure and content

生成的 OpenAPI 规范遵循 [OpenAPI 3.1.0 standard](https://spec.openapis.org/oas/v3.1.0.html) ，并可能在以下简化示例中显示如下：

```json
{
  "openapi": "3.1.0",
  "x-powered-by": "strapi",
  "x-strapi-version": "5.21.0",
  "info": {
    "title": "My Strapi API",
    "description": "API documentation for My Strapi API",
    "version": "1.0.0"
  },
  "paths": {
    "/api/articles": {
      "get": {
        "operationId": "article/get/articles",
        "parameters": [
          {
            "name": "fields",
            "in": "query",
            "schema": {
              "type": "array",
              "items": { "type": "string" }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Article" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Article": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "content": { "type": "string" }
        }
      }
    }
  }
}
```

<div class="mermaid-download-link">
  <small>
    <i class="strapi-icons ph-fill ph-download" style={{color: "inherit;"}}></i>
    <a href="/example-openapi-spec.json"download="" target="_blank" title="点击下载一个完整的 OpenAPI 3.1.0 规范文件，该文件使用从新安装的 Strapi 项目中提取的示例数据生成">Download an example of a complete specification file</a>
  </small>
</div>

<br/>

生成的 OpenAPI 规范包含 Strapi 应用中所有可用的 API 端点，以及有关这些端点的信息，例如：

🌐 The generated OpenAPI specification includes all available API endpoints in your Strapi application, and information about these endpoints, such as the following:

- 适用于所有内容类型的 CRUD 操作
- 应用中定义的自定义 API 路由
- 用于用户管理的身份验证端点
- 用于媒体处理的文件上传端点
- 已安装插件的插件端点

## 配置 {#configuring}

🌐 Configuring

默认情况下，Strapi 不会为生成的 OpenAPI 规范公开 HTTP 端点。要选择启用，请在 `/config/server` 文件中添加一个 `openapi` 键。

🌐 By default, Strapi does not expose HTTP endpoints for the generated OpenAPI specification. To opt in, add an `openapi` key to the `/config/server` file.

### HTTP 端点访问 {#http-endpoint-access}

🌐 HTTP endpoint access

`openapi` 配置接受 2 个子键，`content-api` 和 `admin`，每个都有一个 `access` 属性：

🌐 The `openapi` configuration accepts 2 sub-keys, `content-api` and `admin`, each with an `access` property:

| 子键 | 端点 | `access` 值 | 默认值 | 行为 |
|---------|----------|----------------|---------|----------|
| `content-api` | `GET /api/openapi.json` | `disabled` | 是 | 端点未注册。 |
| `content-api` | `GET /api/openapi.json` | `public` | 否 | 端点可在未认证的情况下访问。 |
| `admin` | `GET /admin/openapi.json` | `disabled` | 是 | 端点未注册。 |
| `admin` | `GET /admin/openapi.json` | `authenticated` | 否 | 端点需要认证的管理员用户。 |

以下示例展示了两个端点：

🌐 The following example exposes both endpoints:

```js title="/config/server.js"
module.exports = {
  openapi: {
    'content-api': {
      access: 'public',
    },
    admin: {
      access: 'authenticated',
    },
  },
};
```

```ts title="/config/server.ts"

  openapi: {
    'content-api': {
      access: 'public',
    },
    admin: {
      access: 'authenticated',
    },
  },
};
```

:::caution

将 `content-api.access` 设置为 `authenticated` 或将 `admin.access` 设置为 `public` 会在启动时抛出错误。

🌐 Setting `content-api.access` to `authenticated` or `admin.access` to `public` throws an error at startup.

:::

:::note

OpenAPI 端点的基于角色的访问控制尚不支持。管理端点使用 `admin::isAuthenticatedAdmin` 策略，并且不按管理员角色或权限进行过滤：任何已认证的管理员用户都可以读取规范。

🌐 Role-based access control for OpenAPI endpoints is not supported yet. The admin endpoint uses the `admin::isAuthenticatedAdmin` policy and does not filter by admin role or permission: any authenticated admin user can read the specification.

:::

:::tip

公共内容 API 规范向任何可以访问该端点的人描述了你的整个内容 API 界面，包括不可公开读取的内容类型。如果你不想在未认证的情况下公开规范，请将 `content-api.access` 保留为 `'disabled'`，并使用 CLI 生成静态文件。

🌐 A public Content API specification describes your entire Content API surface, including content types that are not publicly readable, to anyone who can reach the endpoint. If you do not want to expose the specification without authentication, leave `content-api.access` at `'disabled'` and use the CLI to generate a static file instead.

:::

### 端点选项 {#endpoint-options}

🌐 Endpoint options

除了 `access`，每个端点（`content-api` 和 `admin`）都接受以下选项：

🌐 Besides `access`, each endpoint (`content-api` and `admin`) accepts the following options:

| 选项 | 类型 | 默认值 | 描述 |
|------|------|---------|------|
| `route.path` | 字符串 | `'/openapi.json'` | 规范提供的子路径。在 `content-api` 下解析为 `/api`，在 `admin` 下解析为 `/admin`。 |
| `cache.enabled` | 布尔值 | `true` | 启用基于文件的生成规范缓存。 |
| `cache.maxAgeMs` | 数字 | `60000` | 缓存文件的最大有效期（毫秒），超过该时间规范将被重新生成。 |
| `cache.filePath` | 字符串 | `.strapi/openapi/<type>.json` | 缓存文件路径。相对路径从应用根目录解析。 |

使用默认的 `route.path`，完整的 URL 对于内容 API 端点是 `http://localhost:1337/api/openapi.json`，对于管理端点是 `http://localhost:1337/admin/openapi.json`。

🌐 With the default `route.path`, the full URLs are `http://localhost:1337/api/openapi.json` for the Content API endpoint and `http://localhost:1337/admin/openapi.json` for the Admin endpoint.

:::caution

两个端点必须解析到不同的完整路径。如果 `content-api` 和 `admin` 端点解析到相同的 URL，Strapi 在启动时会抛出错误。

🌐 Both endpoints must resolve to different full paths. If the `content-api` and `admin` endpoints resolve to the same URL, Strapi throws an error at startup.

:::

## 与 Swagger UI 集成 {#integrating-with-swagger-ui}

🌐 Integrating with Swagger UI

:::tip

如果你[公开了一个 HTTP 端点](#http-endpoint-access)，你可以直接将 Swagger UI 指向实时 URL（例如，`http://localhost:1337/api/openapi.json`），而不是生成静态文件。跳过下面的第 1 步，在第 3 步中将端点 URL 用作 `url` 的值。

🌐 If you [exposed an HTTP endpoint](#http-endpoint-access), you can point Swagger UI directly at the live URL (e.g., `http://localhost:1337/api/openapi.json`) instead of generating a static file. Skip step 1 below and use the endpoint URL as the `url` value in step 3.

:::

通过以下步骤，你可以快速生成一个与 [Swagger UI](https://swagger.io/) 兼容的页面：

🌐 With the following steps you can quickly generate a [Swagger UI](https://swagger.io/)-compatible page:

1. 生成规范：

    ```bash
    yarn strapi openapi generate --output ./public/swagger-spec.json
    ```

    ```bash
    npm run strapi openapi generate -- --output ./public/swagger-spec.json
    ```

2. 使用以下代码更新 [ `/config/middlewares.js` 配置文件](/cms/configurations/middlewares)：

    ```js title="/config/middlewares.js"
    module.exports = [
      'strapi::logger',
      'strapi::errors',
      {
        name: 'strapi::security',
        config: {
          contentSecurityPolicy: {
            useDefaults: true,
            directives: {
              'script-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
              'style-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
              'connect-src': ["'self'", 'https:'],
              'img-src': ["'self'", 'data:', 'blob:', 'https:'],
              'media-src': ["'self'", 'data:', 'blob:'],
              upgradeInsecureRequests: null,
            },
          },
        },
      },
      'strapi::cors',
      'strapi::poweredBy',
      'strapi::query',
      'strapi::body',
      'strapi::session',
      'strapi::favicon',
      'strapi::public',
    ];
    ```

    ```js title="/config/middlewares.ts"
    export default [
      'strapi::logger',
      'strapi::errors',
      {
        name: 'strapi::security',
        config: {
          contentSecurityPolicy: {
            useDefaults: true,
            directives: {
              'script-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
              'style-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
              'connect-src': ["'self'", 'https:'],
              'img-src': ["'self'", 'data:', 'blob:', 'https:'],
              'media-src': ["'self'", 'data:', 'blob:'],
              upgradeInsecureRequests: null,
            },
          },
        },
      },
      'strapi::cors',
      'strapi::poweredBy',
      'strapi::query',
      'strapi::body',
      'strapi::session',
      'strapi::favicon',
      'strapi::public',
    ];
    ```

    这将确保来自 [unpkg.com](https://unpkg.com/) 的 Swagger UI 显示不会被由[安全中间件](/cms/configurations/middlewares#security)处理的 Strapi CSP 策略阻止。

3. 在你的 Strapi 项目中创建一个 `public/openapi.html` 文件来显示 Swagger UI，代码如下：

    ```html
    <!DOCTYPE html>
    <html>
      <head>
        <title>API Documentation</title>
        <link
          rel="stylesheet"
          type="text/css"
          href="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui.css"
        />
      </head>
      <body>
        <div id="swagger-ui"></div>
        <script src="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui-bundle.js"></script>
        <script src="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui-standalone-preset.js"></script>
        <script>
          window.onload = function () {
            SwaggerUIBundle({
              url: './swagger-spec.json',
              dom_id: '#swagger-ui',
              presets: [
                SwaggerUIBundle.presets.apis,
                SwaggerUIStandalonePreset
              ],
              layout: 'StandaloneLayout',
            });
          };
        </script>
      </body>
    </html>
    ```

4. 使用 `yarn develop` 或 `npm run develop` 重新启动 Strapi 服务器，然后访问 `/openapi.html` 页面。应该会显示 Swagger UI:

    ![使用 Strapi OpenAPI 规范的 Swagger UI 示例](/img/assets/apis/swagger-open-api.png)
