45个版本 (稳定)

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

1799过程宏

Download history 60483/week @ 2024-05-03 64210/week @ 2024-05-10 60188/week @ 2024-05-17 59809/week @ 2024-05-24 56028/week @ 2024-05-31 59156/week @ 2024-06-07 60058/week @ 2024-06-14 57730/week @ 2024-06-21 56673/week @ 2024-06-28 62455/week @ 2024-07-05 67431/week @ 2024-07-12 72536/week @ 2024-07-19 71504/week @ 2024-07-26 77376/week @ 2024-08-02 77384/week @ 2024-08-09 70840/week @ 2024-08-16

312,183 每月下载次数
474 个crate中使用 (直接使用3个)

MIT/Apache

590KB
12K 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 crate为Rust REST API提供自动生成的OpenAPI文档。它将代码优先方法视为一等公民,并通过提供用于从代码生成文档的简单宏来简化API文档。

它还包含OpenAPI规范的Rust类型,允许你仅在自动生成不是你的口味或不适合你的目的时,仅使用Rust编写OpenAPI规范。

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

Utoipa是框架无关的,可以与任何Web框架一起使用,甚至可以不使用任何框架。虽然它是可移植的和独立的,但其关键特性之一是简单集成到Web框架中。

选择你的风味,并用冰冷的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 框架集成,允许用户在不定义 parameter_in 属性的情况下使用 IntoParams。有关详细信息,请参阅 文档示例
  • debug:向 OpenAPI 定义和其他地方添加额外的特质,如 debug 特质。
  • chrono:支持 chronoDateTimeDateNaiveDateNaiveDateTimeNaiveTimeDuration 类型。默认情况下,这些类型被解析为带有额外 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路径的顺序。如果禁用,路径将按字母顺序排序。
  • 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"] }

注意!要与Swagger UI一起使用utoipa,可以使用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();

有关如何通过它修改生成的OpenAPI的示例,请参阅Modify trait。

超越表面

常见问题解答

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

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

  1. --release 模式构建您的可执行文件
  2. 或将 debug-embed 特性标志添加到您的 Cargo.toml 中的 utoipa-swagger-ui。这将启用 debug-emebed 特性标志,对于 RustEmbed 也是如此。有关更多信息,请参阅 此处此处

在此处找到 utoipa-swagger-ui特性标志

如何为外部类型实现 ToSchema

有几种方法可以解决这个问题,具体细节请参见 此处

如何使用 Rust 的类型别名?

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

自动发现 OpenAPI 架构和路径?

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

许可证

根据您的选择,受 Apache 2.0MIT 许可证的约束。

除非您明确声明,否则您提交给包含在此 crate 中的任何贡献都将双许可,没有任何额外的条款或条件。

依赖项

~0.3–1.8MB
~39K SLoC