From 78570fd72eacdfbd674875f7c8b40e6928baf607 Mon Sep 17 00:00:00 2001 From: Juha Kukkonen Date: Sun, 13 Oct 2024 20:18:53 +0300 Subject: [PATCH] Update docs preparation for v5 (#1119) --- README.md | 108 +++++++++++--------------- examples/README.md | 13 +++- utoipa-gen/src/lib.rs | 3 +- utoipa/src/lib.rs | 173 ++++++++++++++++-------------------------- 4 files changed, 125 insertions(+), 172 deletions(-) diff --git a/README.md b/README.md index 51c6ed0e..21a07b31 100644 --- a/README.md +++ b/README.md @@ -29,28 +29,31 @@ being portable and standalone, one of its key aspects is simple integration with ## Choose your flavor and document your API with ice-cold IPA -Refer to the existing [examples](./examples) for building the "todo" app in the following frameworks: - -- **[actix-web](https://github.com/actix/actix-web)** -- **[axum](https://github.com/tokio-rs/axum)** -- **[warp](https://github.com/seanmonstar/warp)** -- **[tide](https://github.com/http-rs/tide)** -- **[rocket](https://github.com/SergioBenitez/Rocket)** (`0.4` and `0.5`) - -All examples include a [Swagger-UI](https://github.com/swagger-api/swagger-ui) unless stated otherwise. - -There are also examples of building multiple OpenAPI docs in one application, each separated in Swagger UI. -These examples exist only for the **actix** and **warp** frameworks. - -Even if there is no example for your favourite framework, `utoipa` can be used with any -web framework which supports decorating functions with macros similarly to the **warp** and **tide** examples. - -### Community examples - -- **[graphul](https://github.com/graphul-rs/graphul/tree/main/examples/utoipa-swagger-ui)** -- **[salvo](https://github.com/salvo-rs/salvo/tree/main/examples/todos-utoipa)** -- **[viz](https://github.com/viz-rs/viz/tree/main/examples/routing/openapi)** -- **[ntex](https://github.com/leon3s/ntex-rest-api-example)** +|Flavor|Support| +|--|--| +|[actix-web](https://github.com/actix/actix-web)|Parse path, path parameters and query parameters, recognize request body and response body. See more at [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#actix_extras-feature-support-for-actix-web)| +|[axum](https://github.com/tokio-rs/axum)|Parse path and query parameters, recognize request body and response body, [`utoipa-axum` bindings](./utoipa-axum/README.md). See more at [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#axum_extras-feature-support-for-axum)| +|[rocket](https://github.com/SergioBenitez/Rocket)| Parse path, path parameters and query parameters, recognize request body and response body. See more at [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#rocket_extras-feature-support-for-rocket)| +|Others*| Plain `utoipa` without extra flavor. This gives you all the basic benefits listed below in **[Features](#features)** section but with little less automation.| + +> Others* = For example [warp](https://github.com/seanmonstar/warp) but could be anything. + +Refer to the existing [examples](./examples) to find out more. + +## Features + +* OpenAPI 3.1 +* Pluggable, easy setup and integration with frameworks. +* No bloat, enable what you need. +* Support for generic types + * **Note!**
+ Tuples, arrays and slices cannot be used as generic arguments on types. Types implementing `ToSchema` manually should not have generic arguments, as + they are not composeable and will result compile error. +* Automatic schema collection from usages recursively. + * Request body from either handler function arguments (if supported by framework) or from `request_body` attribute. + * Response body from response `body` attribute or response `content` attribute. +* Various OpenAPI visualization tools supported out of the box. +* Rust type aliases via [`utoipa-config`](./utoipa-config/README.md). ## What's up with the word play? @@ -63,9 +66,9 @@ and the `ipa` is _api_ reversed. Aaand... `ipa` is also an awesome type of beer - **`yaml`**: Enables **serde_yaml** serialization of OpenAPI objects. - **`actix_extras`**: Enhances [actix-web](https://github.com/actix/actix-web/) integration with being able to parse `path`, `path` and `query` parameters from actix web path attribute macros. See - [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#actix_extras-support-for-actix-web) or [examples](./examples) for more details. + [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#actix_extras-feature-support-for-actix-web) or [examples](./examples) for more details. - **`rocket_extras`**: Enhances [rocket](https://github.com/SergioBenitez/Rocket) framework integration with being - able to parse `path`, `path` and `query` parameters from rocket path attribute macros. See [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#rocket_extras-support-for-rocket) + able to parse `path`, `path` and `query` parameters from rocket path attribute macros. See [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#rocket_extras-feature-support-for-rocket) or [examples](./examples) for more details. - **`axum_extras`**: Enhances [axum](https://github.com/tokio-rs/axum) framework integration allowing users to use `IntoParams` without defining the `parameter_in` attribute. See [docs](https://docs.rs/utoipa/latest/utoipa/attr.path.html#axum_extras-feature-support-for-axum) @@ -111,7 +114,10 @@ and the `ipa` is _api_ reversed. Aaand... `ipa` is also an awesome type of beer serialization and deserialization of `Arc` and `Rc` types. See more about [serde feature flags](https://serde.rs/feature-flags.html). - **`config`** Enables [`utoipa-config`](./utoipa-config/README.md) for the project which allows defining global configuration options for `utoipa`. -Utoipa implicitly has partial support for `serde` attributes. See [docs](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html#partial-serde-attributes-support) for more details. +### Default Library Support + +* Implicit partial support for `serde` attributes. See [docs](https://docs.rs/utoipa/latest/utoipa/derive.ToSchema.html#partial-serde-attributes-support) for more details. +* Support for [http](https://crates.io/crates/http) `StatusCode` in responses. ## Install @@ -119,26 +125,18 @@ Add minimal dependency declaration to `Cargo.toml`. ```toml [dependencies] -utoipa = "4" +utoipa = "5" ``` -To enable more features such as use actix framework extras you could define the -dependency as follows. - -```toml -[dependencies] -utoipa = { version = "4", features = ["actix_extras"] } -``` - -**Note!** To use `utoipa` together with Swagger UI you can use the [utoipa-swagger-ui](https://docs.rs/utoipa-swagger-ui/) crate. +> [!NOTE] +> 5.0.0 is not yet fully released. Please refer to a tag like `utoipa-4.2.3` for examples of that version. ## Examples -Create a struct, or it could also be an enum. Add `ToSchema` derive macro to it, so it can be registered -as an OpenAPI schema. +_Create type with `ToSchema` and use it in `#[utoipa::path(...)]` that is registered to the `OpenApi`._ ```rust -use utoipa::ToSchema; +use utoipa::{OpenApi, ToSchema}; #[derive(ToSchema)] struct Pet { @@ -146,11 +144,7 @@ struct Pet { name: String, age: Option, } -``` -Create a handler that would handle your business logic and add `path` proc attribute macro over it. - -```rust mod pet_api { /// Get pet by id /// @@ -166,35 +160,24 @@ mod pet_api { ("id" = u64, Path, description = "Pet database id to get Pet for"), ) )] - async fn get_pet_by_id(pet_id: u64) -> Pet { - Pet { + async fn get_pet_by_id(pet_id: u64) -> Result { + Ok(Pet { id: pet_id, age: None, name: "lightning".to_string(), - } + }) } } -``` - -Utoipa has support for [http](https://crates.io/crates/http) `StatusCode` in responses. - -_This attribute macro will create another struct named with `__path_` prefix + handler function name. -So when you implement `some_handler` function in different file and want to export this, make sure `__path_some_handler` -in the module can also be accessible from the root._ - -Tie the `Schema` and the endpoint above to the OpenAPI schema with following `OpenApi` derive proc macro. - -```rust -use utoipa::OpenApi; #[derive(OpenApi)] -#[openapi(paths(pet_api::get_pet_by_id), components(schemas(Pet)))] +#[openapi(paths(pet_api::get_pet_by_id))] struct ApiDoc; println!("{}", ApiDoc::openapi().to_pretty_json().unwrap()); ``` -This would produce an API doc something similar to: +
+ Above example will produce an OpenAPI doc like this: ```json { @@ -282,6 +265,8 @@ This would produce an API doc something similar to: } ``` +
+ ## Modify OpenAPI at runtime You can modify generated OpenAPI at runtime either via generated types directly or using @@ -333,11 +318,6 @@ Find `utoipa-swagger-ui` [feature flags here](https://github.com/juhaku/utoipa/t There are few ways around this that are elaborated [here in detail](https://github.com/juhaku/utoipa/issues/790#issuecomment-1787754185). -### How to define Rust type aliases? - -1. Enable `config` feature flag. -2. See instructions [here](./utoipa-config/README.md). - ### Auto discover for OpenAPI schemas and paths? Currently there is no build in solution to automatically discover the OpenAPI types but for your luck there is a pretty neat crate that diff --git a/examples/README.md b/examples/README.md index 8c68d0cb..b0efd034 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,10 +3,21 @@ This is folder contain a set of examples of utoipa library which should help people to get started with the library. -All examples have their own README.md, and can be seen using two steps: +All examples have their own `README.md`, and can be seen using two steps: 1. Run `cargo run` 2. Browse to `http://localhost:8080/swagger-ui/` or `http://localhost:8080/redoc` or `http://localhost:8080/rapidoc`. `todo-actix`, `todo-axum` and `rocket-todo` have Swagger UI, Redoc, RapiDoc, and Scalar setup, others have Swagger UI if not explicitly stated otherwise. + +Even if there is no example for your favourite framework, `utoipa` can be used with any +web framework which supports decorating functions with macros similarly to the **warp** and **tide** examples. + +## Community examples + +- **[graphul](https://github.com/graphul-rs/graphul/tree/main/examples/utoipa-swagger-ui)** +- **[salvo](https://github.com/salvo-rs/salvo/tree/main/examples/todos-utoipa)** +- **[viz](https://github.com/viz-rs/viz/tree/main/examples/routing/openapi)** +- **[ntex](https://github.com/leon3s/ntex-rest-api-example)** + diff --git a/utoipa-gen/src/lib.rs b/utoipa-gen/src/lib.rs index 6de41e76..ab6e28c8 100644 --- a/utoipa-gen/src/lib.rs +++ b/utoipa-gen/src/lib.rs @@ -1413,7 +1413,8 @@ pub fn derive_to_schema(input: TokenStream) -> TokenStream { /// /// **actix_extras** feature gives **utoipa** ability to parse path operation information from **actix-web** types and macros. /// -/// 1. Ability to parse `path` from **actix-web** path attribute macros e.g. _`#[get(...)]`_. +/// 1. Ability to parse `path` from **actix-web** path attribute macros e.g. _`#[get(...)]`_ or +/// `#[route(...)]`. /// 2. Ability to parse [`std::primitive`] or [`String`] or [`tuple`] typed `path` parameters from **actix-web** _`web::Path<...>`_. /// 3. Ability to parse `path` and `query` parameters form **actix-web** _`web::Path<...>`_, _`web::Query<...>`_ types /// with [`IntoParams`][into_params] trait. diff --git a/utoipa/src/lib.rs b/utoipa/src/lib.rs index 8a0ecd82..5df5c8be 100644 --- a/utoipa/src/lib.rs +++ b/utoipa/src/lib.rs @@ -26,16 +26,31 @@ //! //! # Choose your flavor and document your API with ice cold IPA //! -//! Existing [examples](https://github.com/juhaku/utoipa/tree/master/examples) for following frameworks: +//! |Flavor|Support| +//! |--|--| +//! |[actix-web](https://github.com/actix/actix-web)|Parse path, path parameters and query parameters, recognize request body and response body. See more at [docs][actix_path]| +//! |[axum](https://github.com/tokio-rs/axum)|Parse path and query parameters, recognize request body and response body, [`utoipa-axum` bindings](https://docs.rs/utoipa-axum). See more at [docs][axum_path]| +//! |[rocket](https://github.com/SergioBenitez/Rocket)| Parse path, path parameters and query parameters, recognize request body and response body. See more at [docs][rocket_path]| +//! |Others*| Plain `utoipa` without extra flavor. This gives you all the basic benefits listed below in **[Features](#features)** section but with little less automation.| //! -//! * **actix-web** -//! * **axum** -//! * **warp** -//! * **tide** -//! * **rocket** +//! > Others* = For example [warp](https://github.com/seanmonstar/warp) but could be anything. //! -//! Even if there is no example for your favorite framework `utoipa` can be used with any -//! web framework which supports decorating functions with macros similarly to **warp** and **tide** examples. +//! Refer to the existing [examples](https://github.com/juhaku/utoipa/tree/master/examples) to find out more. +//! +//! ## Features +//! +//! * OpenAPI 3.1 +//! * Pluggable, easy setup and integration with frameworks. +//! * No bloat, enable what you need. +//! * Support for generic types +//! * **Note!**
+//! Tuples, arrays and slices cannot be used as generic arguments on types. Types implementing `ToSchema` manually should not have generic arguments, as +//! they are not composeable and will result compile error. +//! * Automatic schema collection from usages recursively. +//! * Request body from either handler function arguments (if supported by framework) or from `request_body` attribute. +//! * Response body from response `body` attribute or response `content` attribute. +//! * Various OpenAPI visualization tools supported out of the box. +//! * Rust type aliases via [`utoipa-config`][utoipa_config]. //! //! # What's up with the word play? //! @@ -99,7 +114,10 @@ //! * **`config`** Enables [`utoipa-config`](https://docs.rs/utoipa-config/) for the project which allows //! defining global configuration options for `utoipa`. //! -//! Utoipa implicitly has partial support for `serde` attributes. See [`ToSchema` derive][serde] for more details. +//! ### Default Library Support +//! +//! * Implicit partial support for `serde` attributes. See [`ToSchema` derive][serde] for more details. +//! * Support for [http](https://crates.io/crates/http) `StatusCode` in responses. //! //! # Install //! @@ -109,113 +127,54 @@ //! utoipa = "4" //! ``` //! -//! To enable more features such as use actix framework extras you could define the -//! dependency as follows. -//! ```toml -//! [dependencies] -//! utoipa = { version = "4", features = ["actix_extras"] } -//! ``` -//! -//! **Note!** To use `utoipa` together with Swagger UI you can use the [`utoipa-swagger-ui`][utoipa_swagger] crate. -//! -//! [utoipa_swagger]: -//! //! # Examples //! -//! Create a struct, or it could be an enum also. Add `ToSchema` derive macro to it so it can be registered -//! as a component in openapi schema. +//! _**Create type with `ToSchema` and use it in `#[utoipa::path(...)]` that is registered to the `OpenApi`.**_ +//! //! ```rust -//! use utoipa::ToSchema; +//! use utoipa::{OpenApi, ToSchema}; +//! //! #[derive(ToSchema)] //! struct Pet { //! id: u64, //! name: String, //! age: Option, //! } -//! ``` -//! -//! Create an handler that would handle your business logic and add `path` proc attribute macro over it. -//! ```rust -//! mod pet_api { -//! # use utoipa::ToSchema; -//! # -//! # #[derive(ToSchema)] -//! # struct Pet { -//! # id: u64, -//! # name: String, -//! # age: Option, -//! # } -//! /// 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 has support for [http](https://crates.io/crates/http) `StatusCode` in responses. -//! -//! Tie the above component and api to the openapi schema with following `OpenApi` derive proc macro. -//! ```rust -//! # mod pet_api { -//! # use utoipa::ToSchema; +//! # #[derive(Debug)] +//! # struct NotFound; //! # -//! # #[derive(ToSchema)] -//! # struct Pet { -//! # id: u64, -//! # name: String, -//! # age: Option, -//! # } +//! # impl std::error::Error for NotFound {} //! # -//! # /// 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 = 404, 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(), -//! # } -//! # } +//! # impl std::fmt::Display for NotFound { +//! # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +//! # f.write_str("NotFound") +//! # } //! # } -//! # use utoipa::ToSchema; -//! # -//! # #[derive(ToSchema)] -//! # struct Pet { -//! # id: u64, -//! # name: String, -//! # age: Option, -//! # } -//! use utoipa::OpenApi; +//! +//! /// 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), components(schemas(Pet)))] +//! #[openapi(paths(get_pet_by_id))] //! struct ApiDoc; //! //! println!("{}", ApiDoc::openapi().to_pretty_json().unwrap()); @@ -263,10 +222,12 @@ //! * Dump generated API doc to file at build time. See [issue 214 comment](https://github.com/juhaku/utoipa/issues/214#issuecomment-1179589373). //! //! [path]: attr.path.html -//! [rocket_path]: attr.path.html#rocket_extras-support-for-rocket -//! [actix_path]: attr.path.html#actix_extras-support-for-actix-web -//! [axum_path]: attr.path.html#axum_extras-support-for-axum +//! [rocket_path]: attr.path.html#rocket_extras-feature-support-for-rocket +//! [actix_path]: attr.path.html#actix_extras-feature-support-for-actix-web +//! [axum_path]: attr.path.html#axum_extras-feature-support-for-axum //! [serde]: derive.ToSchema.html#partial-serde-attributes-support +//! [utoipa_swagger]: https://docs.rs/utoipa-swagger-ui/ +//! [utoipa_config]: https://docs.rs/utoipa-config/ //! //! [security]: openapi/security/index.html //! [to_schema_derive]: derive.ToSchema.html