juhaku/utoipa

GitHub: juhaku/utoipa

utoipa 是一个 Rust 库,通过编译期代码注解自动生成 OpenAPI 3.1 文档,让开发者告别手动编写 YAML/JSON 的繁琐。

Stars: 3925 | Forks: 356

# utoipa - 自动生成的 OpenAPI 文档 [![Utoipa build](https://static.pigsec.cn/wp-content/uploads/repos/cas/1a/1ac3674fb3daa62469f042c33ded539736a7c00880162539ab5e58b66671ed60.svg)](https://github.com/juhaku/utoipa/actions/workflows/build.yaml) [![crates.io](https://img.shields.io/crates/v/utoipa.svg?label=crates.io&color=orange&logo=rust)](https://crates.io/crates/utoipa) [![docs.rs](https://img.shields.io/static/v1?label=docs.rs&message=utoipa&color=blue&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K)](https://docs.rs/utoipa/latest/utoipa/) ![MSRV](https://img.shields.io/static/v1?label=MSRV&message=1.88&color=orange&logo=rust) 发音为 **_/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 |风味|支持| |--|--| |[actix-web](https://github.com/actix/actix-web)|解析路径、路径参数和查询参数,识别请求体和响应体,[`utoipa-actix-web` 绑定](./utoipa-actix-web/README.md)。在[文档](https://docs.rs/utoipa/latest/utoipa/attr.path.html#actix_extras-feature-support-for-actix-web)中查看更多信息| |[axum](https://github.com/tokio-rs/axum)|解析路径和查询参数,识别请求体和响应体,[`utoipa-axum` 绑定](./utoipa-axum/README.md)。在[文档](https://docs.rs/utoipa/latest/utoipa/attr.path.html#axum_extras-feature-support-for-axum)中查看更多信息| |[rocket](https://github.com/SergioBenitez/Rocket)| 解析路径、路径参数和查询参数,识别请求体和响应体。在[文档](https://docs.rs/utoipa/latest/utoipa/attr.path.html#rocket_extras-feature-support-for-rocket)中查看更多信息| |其他*| 没有额外风味的纯 `utoipa`。这为你提供了下面**[功能](#features)**部分列出的所有基本优势,但自动化程度稍低。| 请参阅现有的[示例](./examples)了解更多信息。 ## 功能 * OpenAPI 3.1 * 可插拔,易于设置并与框架集成。 * 没有冗余,按需启用。 * 支持泛型类型 * **注意!**
Tuples、arrays 和 slices 不能用作类型的泛型参数。手动实现 `ToSchema` 的类型不应有泛型参数,因为 它们无法组合,并会导致编译错误。 * 递归收集用法的自动 schema 收集。 * 来自处理函数参数(如果框架支持)或 `request_body` 属性的请求体。 * 来自响应 `body` 属性或响应 `content` 属性的响应体。 * 开箱即支持多种 OpenAPI 可视化工具。 * 通过 [`utoipa-config`](./utoipa-config/README.md) 支持 Rust 类型别名。 ## 这个文字游戏是怎么回事? 这个名字来源于单词 `utopic` 和 `api`,其中 `uto` 是 _utopic_ 的前三个字母, 而 `ipa` 是 _api_ 的反向拼写。而且…… `ipa` 也是一种很棒的啤酒 :beer:。 ## Crate 功能 - **`macros`** 启用 `utoipa-gen` 宏。**默认启用。** - **`yaml`**: 启用 OpenAPI 对象的 **yaml_serde** 序列化。 - **`actix_extras`**: 增强 [actix-web](https://github.com/actix/actix-web/) 集成,能够 从 actix web 路径属性宏中解析 `path`、`path` 和 `query` 参数。详见 [文档](https://docs.rs/utoipa/latest/utoipa/attr.path.html#actix_extras-feature-support-for-actix-web)或[示例](./examples)。 - **`rocket_extras`**: 增强 [rocket](https://github.com/SergioBenitez/Rocket) 框架集成,能够 从 rocket 路径属性宏中解析 `path`、`path` 和 `query` 参数。详见 [文档](https://docs.rs/utoipa/latest/utoipa/attr.path.html#rocket_extras-feature-support-for-rocket) 或[示例](./examples)。 - **`axum_extras`**: 增强 [axum](https://github.com/tokio-rs/axum) 框架集成,允许用户使用 `IntoParams` 而无需 定义 `parameter_in` 属性。详见 [文档](https://docs.rs/utoipa/latest/utoipa/attr.path.html#axum_extras-feature-support-for-axum) 或[示例](./examples)。 - **`debug`**: 为 openapi 定义及其他地方添加额外的 trait,如 debug trait。 - **`chrono`**: 添加对 [chrono](https://crates.io/crates/chrono) `DateTime`、`Date`、`NaiveDate`、`NaiveDateTime`、`NaiveTime` 和 `Duration` 类型的支持。默认情况下,这些类型会被解析为带有额外 `format` 信息的 `string` 类型。 `DateTime` 和 `NaiveDateTime` 使用 `format: date-time`,而 `Date` 和 `NaiveDate` 根据 [RFC3339](https://www.rfc-editor.org/rfc/rfc3339#section-5.6) 作为 `ISO-8601` 使用 `format: date`。要 覆盖默认的 `string` 表示,用户必须使用 `value_type` 属性来覆盖该类型。 详见[文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html)。 - **`time`**: 添加对 [time](https://crates.io/crates/time) `OffsetDateTime`、`PrimitiveDateTime`、`Date` 和 `Duration` 类型的支持。 默认情况下,这些类型会被解析为 `string`。`OffsetDateTime` 和 `PrimitiveDateTime` 将使用 `date-time` 格式。`Date` 将使用 `date` 格式,而 `Duration` 将没有任何格式。要覆盖默认的 `string` 表示,用户必须使用 `value_type` 属性 来覆盖该类型。详见[文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html)。 - **`jiff_0_2`** 添加对 [jiff 0.2](https://crates.io/crates/jiff) `Timestamp`、`Zoned` 和 `civil::Date` 类型的支持。 默认情况下,这些类型会被解析为 `string`。`Timestamp` 和 `Zoned` 将使用 `date-time` 格式。`civil::Date` 将使用 `date` 格式。要覆盖默认的 `string` 表示,用户必须使用 `value_type` 属性 来覆盖该类型。详见[文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html)。 - **`decimal`**: 添加对 [rust_decimal](https://crates.io/crates/rust_decimal) `Decimal` 类型的支持。**默认情况下** 它会被解释为 `String`。如果你想更改格式,需要覆盖该类型。 参见[组件派生文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html)中的 `value_type`。 - **`decimal_float`**: 添加对 [rust_decimal](https://crates.io/crates/rust_decimal) `Decimal` 类型的支持。**默认情况下** 它会被解释为 `Number`。此功能与 **decimal** 互斥,并允许更改 文档中用于 `Decimal` 的默认类型,非常类似于 rust_decimal 暴露的 `serde_with_float` 功能。 - **`bigdecimal`**: 添加对 [bigdecimal](https://crates.io/crates/bigdecimal) `BigDecimal` 类型的支持。**默认情况下** 它会被解释为 `String`。如果你想更改格式,需要覆盖该类型。 参见[组件派生文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html)中的 `value_type`。 - **`bigdecimal_float`**: 添加对 [bigdecimal](https://crates.io/crates/bigdecimal) `BigDecimal` 类型的支持。**默认情况下** 它会被解释为 `Number`。此功能与 **bigdecimal** 互斥,并允许更改 文档中用于 `BigDecimal` 的默认类型。 - **`uuid`**: 添加对 [uuid](https://github.com/uuid-rs/uuid) 的支持。`Uuid` 类型将在 OpenAPI 规范中呈现为带有 `uuid` 格式的 `String`。 - **`ulid`**: 添加对 [ulid](https://github.com/dylanhart/ulid-rs) 的支持。`Ulid` 类型将在 OpenAPI 规范中呈现为带有 `ulid` 格式的 `String`。 - **`url`**: 添加对 [url](https://github.com/servo/rust-url) 的支持。`Url` 类型将在 OpenAPI 规范中呈现为带有 `uri` 格式的 `String`。 - **`smallvec`**: 添加对 [smallvec](https://crates.io/crates/smallvec) 的支持。`SmallVec` 将被视为 `Vec`。 - **`openapi_extensions`**: 添加提供额外便利功能的 trait 和函数。 参见 [`request_body` 文档](https://docs.rs/utoipa/latest/utoipa/openapi/request_body)中的示例。 - **`repr`**: 为 C 风格枚举表示,添加对 [repr_serde](https://github.com/dtolnay/serde-repr) 的 `repr(u*)` 和 `repr(i*)` 属性的支持,用于单元类型枚举。详见[文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html)。 - **`preserve_order`**: 在为组件序列化 schema 时保持属性的顺序。 启用后,属性将按照相应结构体定义中字段的顺序列出。 禁用时,属性将按字母顺序列出。 - **`preserve_path_order`**: 根据 OpenAPI Paths 引入到 `#[openapi(paths(...))]` 宏属性的顺序保持其顺序。如果禁用,paths 将按 字母顺序排序。**然而**,根据[规范](https://spec.openapis.org/oas/latest.html#fixed-fields-6),path 下的操作顺序**将**始终保持不变 - **`indexmap`**: 添加对 [indexmap](https://crates.io/crates/indexmap) 的支持。启用后,`IndexMap` 将渲染为类似于 `BTreeMap` 和 `HashMap` 的 map。 - **`non_strict_integers`**: 添加对非标准整数格式 `int8`、`int16`、`uint8`、`uint16`、`uint32` 和 `uint64` 的支持。 - **`rc_schema`**: 为 `Arc` 和 `Rc` 类型添加 `ToSchema` 支持。**注意!** 必须单独启用 serde `rc` 功能标志,以允许 `Arc` 和 `Rc` 类型的序列化和反序列化。详见 [serde 功能标志](https://serde.rs/feature-flags.html)。 - **`config`** 为项目启用 [`utoipa-config`](./utoipa-config/README.md),允许为 `utoipa` 定义全局配置选项。 ### 默认库支持 * 隐式部分支持 `serde` 属性。详见[文档](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html#partial-serde-attributes-support)。 * 在响应中支持 [http](https://crates.io/crates/http) `StatusCode`。 ## 安装 将依赖声明添加到 `Cargo.toml`。 ``` [dependencies] utoipa = "5" ``` ## 示例 _使用 `ToSchema` 创建类型,并在 `#[utoipa::path(...)]` 中使用它,然后注册到 `OpenApi`。_ ``` use utoipa::{OpenApi, ToSchema}; #[derive(ToSchema)] struct Pet { id: u64, name: String, age: Option, } 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) -> Result { Ok(Pet { id: pet_id, age: None, name: "lightning".to_string(), }) } } #[derive(OpenApi)] #[openapi(paths(pet_api::get_pet_by_id))] struct ApiDoc; println!("{}", ApiDoc::openapi().to_pretty_json().unwrap()); ```
上面的示例将生成如下的 OpenAPI 文档: ``` { "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](https://docs.rs/utoipa/latest/utoipa/trait.Modify.html) 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](https://docs.rs/utoipa/latest/utoipa/openapi/struct.OpenApi.html) 转换为 [OpenApiBuilder](https://docs.rs/utoipa/latest/utoipa/openapi/struct.OpenApiBuilder.html)。_ ``` let builder: OpenApiBuilder = ApiDoc::openapi().into(); ``` 有关如何通过 [Modify](https://docs.rs/utoipa/latest/utoipa/trait.Modify.html) trait 修改生成的 OpenAPI 的示例,请参见该 trait。 ## 深入探索 - 了解如何通过 Swagger UI 提供 OpenAPI 文档,请查看 [utoipa-swagger-ui](https://docs.rs/utoipa-swagger-ui/) crate 了解更多详情。 - 浏览[示例](https://github.com/juhaku/utoipa/tree/master/examples)获取更全面的示例。 - 查看 [IntoResponses](https://docs.rs/utoipa/latest/utoipa/derive.IntoResponses.html) 和 [ToResponse](https://docs.rs/utoipa/latest/utoipa/derive.ToResponse.html) 获取派生响应的示例。 - 在[安全文档](https://docs.rs/utoipa/latest/utoipa/openapi/security/index.html)中了解更多关于 OpenAPI 安全的信息。 - 在构建时将生成的 API 文档转储到文件。参见 [issue 214 评论](https://github.com/juhaku/utoipa/issues/214#issuecomment-1179589373)。 ## 常见问题 ### 如何为外部类型实现 `ToSchema`? 有几种方法可以解决这个问题,[这里](https://github.com/juhaku/utoipa/issues/790#issuecomment-1787754185)有详细说明。 ### 自动发现 OpenAPI schema 和 path? 目前没有内置的解决方案来自动发现 OpenAPI 类型,但幸运,有一个非常棒的 crate 刚好可以为你做到这一点,它叫 [utoipauto](https://github.com/ProbablyClem/utoipauto)。 ## 许可证 根据你的选择,受 [Apache 2.0](LICENSE-APACHE) 或 [MIT](LICENSE-MIT) 许可证管辖。 除非你另有明确声明,否则你故意提交以包含在此 crate 中的任何贡献, 均应获得双重许可,无需任何附加条款或条件。
标签:API文档, OpenAPI, Rust, SOC Prime, Swagger, Syscall, Web开发, 可视化界面, 开发工具, 网络流量审计, 通知系统