46 个版本 (稳定版)

5.0.0-alpha.2 2024 年 8 月 23 日
5.0.0-alpha.12024 年 7 月 27 日
5.0.0-alpha.02024 年 5 月 30 日
4.2.3 2024 年 5 月 7 日
0.1.0-beta62022 年 3 月 7 日

#19网页编程

Download history 61212/week @ 2024-05-03 64513/week @ 2024-05-10 60255/week @ 2024-05-17 59879/week @ 2024-05-24 56090/week @ 2024-05-31 59224/week @ 2024-06-07 60132/week @ 2024-06-14 57751/week @ 2024-06-21 56631/week @ 2024-06-28 62389/week @ 2024-07-05 67425/week @ 2024-07-12 72514/week @ 2024-07-19 71467/week @ 2024-07-26 77372/week @ 2024-08-02 77481/week @ 2024-08-09 70861/week @ 2024-08-16

312,232 每月下载量
用于 473 个包 (433 个直接使用)

MIT/Apache 许可

380KB
6K SLoC

utoipa - 自动生成的 OpenAPI 文档

Utoipa build crates.io docs.rs MSRV

发音为 /u:ˈtoʊ:i.pɑ//u:ˈtoʊˌaɪ.piˈeɪ/,哪种对你来说更方便。

想用 OpenAPI 记录您的 API,但又不想手动调整 YAML 或 JSON?希望它足够简单,几乎达到理想状态?不用担心:utoipa 就是为了填补这个空缺而生的。它的目标是,如果不是全部,至少完成大部分繁重的工作,让您能专注于编写实际的 API 逻辑而不是文档。它旨在做到 最小化简单快速。它使用简单的 proc 宏,您可以使用它来注释您的代码以便文档化。

utoipa 包为 Rust REST API 提供自动生成的 OpenAPI 文档。它将代码优先方法视为一等公民,并通过提供简单的宏来简化 API 文档的生成。

它还包含 OpenAPI 规范的 Rust 类型,允许您仅使用 Rust 编写 OpenAPI 规范,如果自动生成不是您的首选或不符合您的目的。

该库的长期目标是成为在 Rust 代码库中需要 OpenAPI 文档时的首选之地。

Utoipa 是框架无关的,可以与任何网页框架一起使用,甚至在没有框架的情况下使用。虽然它是可移植的和独立的,但其关键特性之一是与网页框架的简单集成。

选择您喜欢的口味,并用冰冷的 IPA 记录您的 API

请参考以下框架中构建 "todo" 应用的现有 示例

所有示例均包含 Swagger-UI,除非另有说明。

在单个应用程序中构建多个 OpenAPI 文档的例子也存在,每个都在 Swagger UI 中独立显示。这些例子仅适用于 actixwarp 框架。

即使没有您喜欢的框架的示例,utoipa 也可以与任何支持用宏装饰函数的 Web 框架一起使用,类似于 warptide 示例。

社区示例

这个文字游戏是什么意思?

这个名字来自单词 utopicapi,其中 utoutopic 的前三个字母,而 ipaapi 的反转。而且... ipa 还是一种很棒的啤酒类型 🍺。

包功能

  • yaml:启用 OpenAPI 对象的 serde_yaml 序列化。
  • actix_extras:增强 actix-web 集成,能够从 actix web 路径属性宏解析 pathquery 参数。有关详细信息,请参阅 文档示例
  • rocket_extras:增强 rocket 框架集成,能够从 rocket 路径属性宏解析 pathquery 参数。有关详细信息,请参阅 文档示例
  • axum_extras:增强 axum 框架集成,允许用户使用 IntoParams 而无需定义 parameter_in 属性。有关详细信息,请参阅 文档示例
  • debug:向 openapi 定义和其他地方添加额外的特质,如 debug 特质。
  • chrono:添加对 chrono DateTimeDateNaiveDateNaiveDateTimeNaiveTimeDuration 类型的支持。默认情况下,这些类型将解析为带额外 format 信息的 string 类型。对于 DateTimeNaiveDateTime 使用 format: date-time,对于 DateNaiveDate 使用 format: date,根据 RFC3339 作为 ISO-8601。要覆盖默认的 string 表示,用户必须使用 value_type 属性来覆盖类型。有关详细信息,请参阅 文档
  • time:添加对 time OffsetDateTimePrimitiveDateTimeDateDuration 类型的支持。默认情况下,这些类型被解析为 stringOffsetDateTimePrimitiveDateTime 将使用 date-time 格式。 Date 将使用 date 格式,而 Duration 不会有任何格式。要覆盖默认的 string 表示形式,用户必须使用 value_type 属性来覆盖类型。有关更多详细信息,请参阅 文档
  • decimal:添加对 rust_decimal Decimal 类型的支持。默认情况下,它被解释为 String。如果您想更改格式,您需要覆盖类型。请参阅 组件派生文档 中的 value_type
  • decimal_float:添加对 rust_decimal Decimal 类型的支持。默认情况下,它被解释为 Number。此功能与 decimal 兼容,允许您更改文档中用于 Decimal 的默认类型,就像 rust_decimal 提供的 serde_with_float 功能一样。
  • uuid:添加对 uuid 的支持。在 OpenAPI 规范中,Uuid 类型将被表示为格式为 uuidString
  • ulid:添加对 ulid 的支持。在 OpenAPI 规范中,Ulid 类型将被表示为格式为 ulidString
  • url:添加对 url 的支持。在 OpenAPI 规范中,Url 类型将被表示为格式为 uriString
  • smallvec:添加对 smallvec 的支持。将 SmallVec 视为 Vec
  • openapi_extensions:添加了提供额外便捷函数的特性和函数。请参阅 request_body 文档 中的示例。
  • repr:为单元类型枚举添加对 repr_serderepr(u*)repr(i*) 属性的支持,以实现类似 C 枚举的表示。请参阅 文档 以获取更多详细信息。
  • preserve_order:在序列化组件的方案时保留属性的顺序。启用时,属性将按照相应结构定义中字段的顺序列出。禁用时,属性将按字母顺序列出。
  • preserve_path_order:保留 OpenAPI 路径的顺序,按照它们被引入到 #[openapi(paths(...))] 宏属性的顺序。如果禁用,则路径将按字母顺序排序。
  • indexmap:添加对 indexmap 的支持。启用后,IndexMap 将被渲染为类似于 BTreeMapHashMap 的映射。
  • non_strict_integers:添加对非标准整数格式 int8int16uint8uint16uint32uint64 的支持。
  • rc_schema:为 Arc<T>Rc<T> 类型添加 ToSchema 支持。**注意**!必须单独启用 serde rc 功能标志,以允许对 Arc<T>Rc<T> 类型进行序列化和反序列化。有关更多信息,请参阅 serde 功能标志

Utoipa 默认部分支持 serde 属性。有关更多详细信息,请参阅 文档

安装

将最小依赖声明添加到 Cargo.toml

[dependencies]
utoipa = "4"

要启用更多功能,例如使用 actix 框架扩展,可以将依赖项定义如下。

[dependencies]
utoipa = { version = "4", features = ["actix_extras"] }

**注意**!要使用 utoipa 与 Swagger UI 一起使用,可以使用 utoipa-swagger-ui crate。

示例

创建一个结构体,或者它也可以是一个枚举。将其添加到 ToSchema derive 宏,以便它可以注册为 OpenAPI 模式。

use utoipa::ToSchema;

#[derive(ToSchema)]
struct Pet {
   id: u64,
   name: String,
   age: Option<i32>,
}

创建一个处理程序来处理您的业务逻辑,并在其上添加 path proc 属性宏。

mod pet_api {
    /// Get pet by id
    ///
    /// Get pet from database by pet id
    #[utoipa::path(
        get,
        path = "/pets/{id}",
        responses(
            (status = 200, description = "Pet found successfully", body = Pet),
            (status = NOT_FOUND, description = "Pet was not found")
        ),
        params(
            ("id" = u64, Path, description = "Pet database id to get Pet for"),
        )
    )]
    async fn get_pet_by_id(pet_id: u64) -> Pet {
        Pet {
            id: pet_id,
            age: None,
            name: "lightning".to_string(),
        }
    }
}

Utoipa 支持响应中的 http StatusCode

此属性宏将创建一个名为 __path_ 前缀 + 处理程序函数名称的新结构体。因此,当您在另一个文件中实现 some_handler 函数并想要导出它时,请确保模块中的 __path_some_handler 可以从根访问。

使用以下 OpenApi derive proc 宏将 Schema 和上述端点与 OpenAPI 模式关联起来。

use utoipa::OpenApi;

#[derive(OpenApi)]
#[openapi(paths(pet_api::get_pet_by_id), components(schemas(Pet)))]
struct ApiDoc;

println!("{}", ApiDoc::openapi().to_pretty_json().unwrap());

这将生成类似于以下内容的 API 文档:

{
  "openapi": "3.1.0",
  "info": {
    "title": "application name from Cargo.toml",
    "description": "description from Cargo.toml",
    "contact": {
      "name": "author name from Cargo.toml",
      "email": "author email from Cargo.toml"
    },
    "license": {
      "name": "license from Cargo.toml"
    },
    "version": "version from Cargo.toml"
  },
  "paths": {
    "/pets/{id}": {
      "get": {
        "tags": [
          "pet_api"
        ],
        "summary": "Get pet by id",
        "description": "Get pet from database by pet id",
        "operationId": "get_pet_by_id",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Pet database id to get Pet for",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pet found successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pet"
                }
              }
            }
          },
          "404": {
            "description": "Pet was not found"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Pet": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "age": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "id": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "name": {
            "type": "string"
          }
        }
      }
    }
  }
}

在运行时修改 OpenAPI

您可以通过生成的类型直接或使用 Modify trait 来修改生成的 OpenAPI。

直接通过类型修改生成的 OpenAPI。

#[derive(OpenApi)]
#[openapi(
    info(description = "My Api description"),
)]
struct ApiDoc;

let mut doc = ApiDoc::openapi();
doc.info.title = String::from("My Api");

您甚至可以将生成的 OpenApi 转换为 OpenApiBuilder

let builder: OpenApiBuilder = ApiDoc::openapi().into();

请参阅Modify特质以获取如何通过它修改生成的OpenAPI的示例。

深入了解

  • 查看如何通过Swagger UI提供服务端OpenAPI文档,请查阅utoipa-swagger-ui存储库以获取更多详细信息。
  • 浏览示例以获取更全面的示例。
  • 请查看IntoResponsesToResponse以了解如何派生响应。
  • 有关OpenAPI安全性的更多信息,请参阅安全文档
  • 在构建时将生成的API文档输出到文件。请参阅问题214评论

常见问题解答(FAQ)

Swagger UI从构建的二进制文件返回404NotFound

这很可能是因为RustEmbed没有将Swagger UI嵌入到可执行文件中。这是自然的,因为RustEmbed库在默认情况下不会在调试构建中嵌入文件。为了解决这个问题,您可以执行以下操作之一。

  1. --release模式构建您的可执行文件
  2. 或向您的Cargo.toml中的utoipa-swagger-ui添加debug-embed功能标志。这将启用debug-emebed功能标志,同时为RustEmbed。有关更多信息,请参阅此处此处

在此处找到utoipa-swagger-ui的功能标志。

如何为外部类型实现ToSchema

有几种方法可以解决这个问题,具体请参阅此处的详细说明。

如何使用Rust的类型别名?

目前这是不可能的,因为没有方法可以评估proc宏代码生成中可见的类型令牌背后的实际类型。如果可以实现全局别名注册,这可能在将来成为可能。有关此问题的相关问题,请参阅#766

如何自动发现OpenAPI模式和路径?

目前没有内置的解决方案来自动发现OpenAPI类型,但幸运的是,有一个非常棒的存储库可以为您完成这项工作,名为utoipauto

许可证

根据您的选择,在Apache 2.0MIT许可证下授权。

除非您明确说明,否则您提交给包括在此存储库中的任何贡献,都应双重授权,没有任何额外的条款或条件。

依赖关系

~1.5–3.5MB
~73K SLoC