From 93dfaf13035794b7437184f89b998e6afb0ca970 Mon Sep 17 00:00:00 2001 From: Tim DuBois Date: Tue, 28 Nov 2023 11:09:06 +0100 Subject: [PATCH] Axum 0.7 bindings (#807) Update to axum `0.7`. Also update docs, READMEs, examples and fix tests. This is a breaking change that removes the body generic argument from axum `HttpRouter`. --- examples/todo-axum/Cargo.toml | 4 ++-- examples/todo-axum/src/main.rs | 8 +++++--- utoipa-gen/Cargo.toml | 2 +- utoipa-rapidoc/Cargo.toml | 2 +- utoipa-rapidoc/README.md | 6 +++--- utoipa-rapidoc/src/lib.rs | 13 +++++-------- utoipa-redoc/Cargo.toml | 2 +- utoipa-redoc/README.md | 6 +++--- utoipa-redoc/src/axum.rs | 6 ++---- utoipa-redoc/src/lib.rs | 7 +++---- utoipa-swagger-ui/Cargo.toml | 2 +- utoipa-swagger-ui/README.md | 2 +- utoipa-swagger-ui/src/axum.rs | 15 ++++++--------- utoipa-swagger-ui/src/lib.rs | 7 +++---- 14 files changed, 37 insertions(+), 45 deletions(-) diff --git a/examples/todo-axum/Cargo.toml b/examples/todo-axum/Cargo.toml index e8504898..e26d5951 100644 --- a/examples/todo-axum/Cargo.toml +++ b/examples/todo-axum/Cargo.toml @@ -11,8 +11,8 @@ authors = [ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -axum = "0.6" -hyper = { version = "0.14", features = ["full"] } +axum = "0.7" +hyper = { version = "1.0.1", features = ["full"] } tokio = { version = "1.17", features = ["full"] } tower = "0.4" utoipa = { path = "../../utoipa", features = ["axum_extras"] } diff --git a/examples/todo-axum/src/main.rs b/examples/todo-axum/src/main.rs index adb66d09..dda235ef 100644 --- a/examples/todo-axum/src/main.rs +++ b/examples/todo-axum/src/main.rs @@ -3,8 +3,9 @@ use std::{ sync::Arc, }; -use axum::{routing, Router, Server}; -use hyper::Error; +use axum::{routing, Router}; +use std::io::Error; +use tokio::net::TcpListener; use utoipa::{ openapi::security::{ApiKey, ApiKeyValue, SecurityScheme}, Modify, OpenApi, @@ -70,7 +71,8 @@ async fn main() -> Result<(), Error> { .with_state(store); let address = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8080)); - Server::bind(&address).serve(app.into_make_service()).await + let listener = TcpListener::bind(&address).await?; + axum::serve(listener, app.into_make_service()).await } mod todo { diff --git a/utoipa-gen/Cargo.toml b/utoipa-gen/Cargo.toml index 043c9d52..ef8ad82a 100644 --- a/utoipa-gen/Cargo.toml +++ b/utoipa-gen/Cargo.toml @@ -27,7 +27,7 @@ utoipa = { path = "../utoipa", features = ["uuid"], default-features = false } serde_json = "1" serde = "1" actix-web = { version = "4", features = ["macros"], default-features = false } -axum = "0.6" +axum = "0.7" paste = "1" rocket = { version = "0.5.0-rc.3", features = ["json"] } smallvec = { version = "1.10", features = ["serde"] } diff --git a/utoipa-rapidoc/Cargo.toml b/utoipa-rapidoc/Cargo.toml index b3ef4c64..be7858d0 100644 --- a/utoipa-rapidoc/Cargo.toml +++ b/utoipa-rapidoc/Cargo.toml @@ -20,4 +20,4 @@ serde_json = { version = "1.0" } utoipa = { version = "4", path = "../utoipa" } actix-web = { version = "4", optional = true, default-features = false } rocket = { version = "0.5.0-rc.3", features = ["json"], optional = true } -axum = { version = "0.6", optional = true } +axum = { version = "0.7", optional = true } diff --git a/utoipa-rapidoc/README.md b/utoipa-rapidoc/README.md index 7a490e59..351587c6 100644 --- a/utoipa-rapidoc/README.md +++ b/utoipa-rapidoc/README.md @@ -17,7 +17,7 @@ You may find fullsize examples from utoipa's Github [repository][examples]. * **actix-web** Allows serving `RapiDoc` via _**`actix-web`**_. `version >= 4` * **rocket** Allows serving `RapiDoc` via _**`rocket`**_. `version >=0.5.0-rc.3` -* **axum** Allows serving `RapiDoc` via _**`axum`**_. `version >=0.6` +* **axum** Allows serving `RapiDoc` via _**`axum`**_. `version >=0.7` # Install @@ -92,9 +92,9 @@ rocket::build() _**Serve `RapiDoc` via `axum` framework.**_ ```rust - use axum::{Router, body::HttpBody}; + use axum::Router; use utoipa_rapidoc::RapiDoc; - let app = Router::::new() + let app = Router::::new() .merge(RapiDoc::with_openapi("/rapidoc", ApiDoc::openapi())); ``` diff --git a/utoipa-rapidoc/src/lib.rs b/utoipa-rapidoc/src/lib.rs index 938c9e90..2b5cbe8f 100644 --- a/utoipa-rapidoc/src/lib.rs +++ b/utoipa-rapidoc/src/lib.rs @@ -112,20 +112,19 @@ //! //! _**Serve [`RapiDoc`] via `axum` framework.**_ //! ```no_run -//! use axum::{Router, body::HttpBody}; +//! use axum::Router; //! use utoipa_rapidoc::RapiDoc; //! # use utoipa::OpenApi; //! # #[derive(OpenApi)] //! # #[openapi()] //! # struct ApiDoc; //! # -//! # fn inner() +//! # fn inner() //! # where -//! # B: HttpBody + Send + 'static, //! # S: Clone + Send + Sync + 'static, //! # { //! -//! let app = Router::::new() +//! let app = Router::::new() //! .merge(RapiDoc::with_openapi("/rapidoc", ApiDoc::openapi())); //! # } //! ``` @@ -304,23 +303,21 @@ mod acitx { mod axum { #![cfg(feature = "axum")] - use axum::body::HttpBody; use axum::response::Html; use axum::{routing, Json, Router}; use crate::RapiDoc; - impl From> for Router + impl From> for Router where R: Clone + Send + Sync + 'static, - B: HttpBody + Send + 'static, { fn from(value: RapiDoc<'_, '_, '_>) -> Self { let html = value.to_html(); let openapi = value.openapi; let mut router = - Router::::new().route(value.path, routing::get(move || async { Html(html) })); + Router::::new().route(value.path, routing::get(move || async { Html(html) })); if let Some(openapi) = openapi { router = router.route( diff --git a/utoipa-redoc/Cargo.toml b/utoipa-redoc/Cargo.toml index a536d2b9..8399606b 100644 --- a/utoipa-redoc/Cargo.toml +++ b/utoipa-redoc/Cargo.toml @@ -20,4 +20,4 @@ serde_json = { version = "1.0" } utoipa = { version = "4", path = "../utoipa" } actix-web = { version = "4", optional = true, default-features = false } rocket = { version = "0.5.0-rc.3", features = ["json"], optional = true } -axum = { version = "0.6", optional = true } +axum = { version = "0.7", optional = true } diff --git a/utoipa-redoc/README.md b/utoipa-redoc/README.md index 9da0dcc1..d6816079 100644 --- a/utoipa-redoc/README.md +++ b/utoipa-redoc/README.md @@ -17,7 +17,7 @@ You may find fullsize examples from utoipa's Github [repository][examples]. * **actix-web** Allows serving `Redoc` via _**`actix-web`**_. `version >= 4` * **rocket** Allows serving `Redoc` via _**`rocket`**_. `version >=0.5.0-rc.3` -* **axum** Allows serving `Redoc` via _**`axum`**_. `version >=0.6` +* **axum** Allows serving `Redoc` via _**`axum`**_. `version >=0.7` # Install @@ -111,10 +111,10 @@ rocket::build() _**Serve `Redoc` via `axum` framework.**_ ```rust - use axum::{Router, body::HttpBody}; + use axum::Router; use utoipa_redoc::{Redoc, Servable}; - let app = Router::::new() + let app = Router::::new() .merge(Redoc::with_url("/redoc", ApiDoc::openapi())); ``` diff --git a/utoipa-redoc/src/axum.rs b/utoipa-redoc/src/axum.rs index 474f45d9..9c0cb6d3 100644 --- a/utoipa-redoc/src/axum.rs +++ b/utoipa-redoc/src/axum.rs @@ -1,19 +1,17 @@ #![cfg(feature = "axum")] -use axum::body::HttpBody; use axum::response::Html; use axum::{routing, Router}; use crate::{Redoc, Spec}; -impl<'s, 'u, S: Spec, R, B> From> for Router +impl<'s, 'u, S: Spec, R> From> for Router where R: Clone + Send + Sync + 'static, - B: HttpBody + Send + 'static, 's: 'static, { fn from(value: Redoc<'s, 'u, S>) -> Self { let html = value.to_html(); - Router::::new().route(value.url, routing::get(move || async { Html(html) })) + Router::::new().route(value.url, routing::get(move || async { Html(html) })) } } diff --git a/utoipa-redoc/src/lib.rs b/utoipa-redoc/src/lib.rs index bad67aa0..d57b7d38 100644 --- a/utoipa-redoc/src/lib.rs +++ b/utoipa-redoc/src/lib.rs @@ -145,20 +145,19 @@ //! //! _**Serve [`Redoc`] via `axum` framework.**_ //! ```no_run -//! use axum::{Router, body::HttpBody}; +//! use axum::Router; //! use utoipa_redoc::{Redoc, Servable}; //! # use utoipa::OpenApi; //! # #[derive(OpenApi)] //! # #[openapi()] //! # struct ApiDoc; //! # -//! # fn inner() +//! # fn inner() //! # where -//! # B: HttpBody + Send + 'static, //! # S: Clone + Send + Sync + 'static, //! # { //! -//! let app = Router::::new() +//! let app = Router::::new() //! .merge(Redoc::with_url("/redoc", ApiDoc::openapi())); //! # } //! ``` diff --git a/utoipa-swagger-ui/Cargo.toml b/utoipa-swagger-ui/Cargo.toml index a91a82bc..8796010f 100644 --- a/utoipa-swagger-ui/Cargo.toml +++ b/utoipa-swagger-ui/Cargo.toml @@ -19,7 +19,7 @@ rust-embed = { version = "8", features = ["interpolate-folder-path"] } mime_guess = { version = "2.0" } actix-web = { version = "4", optional = true, default-features = false } rocket = { version = "0.5.0-rc.3", features = ["json"], optional = true } -axum = { version = "0.6", optional = true } +axum = { version = "0.7", optional = true } utoipa = { version = "4", path = "../utoipa" } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0" } diff --git a/utoipa-swagger-ui/README.md b/utoipa-swagger-ui/README.md index 2ea61ad1..c0d30e4b 100644 --- a/utoipa-swagger-ui/README.md +++ b/utoipa-swagger-ui/README.md @@ -13,7 +13,7 @@ works as a bridge for serving the OpenAPI documentation created with * **actix-web** `version >= 4` * **rocket** `version >=0.5.0-rc.3` -* **axum** `version >=0.6` +* **axum** `version >=0.7` Serving Swagger UI is framework independent thus this crate also supports serving the Swagger UI with other frameworks as well. With other frameworks, there is a bit more manual implementation to be done. See diff --git a/utoipa-swagger-ui/src/axum.rs b/utoipa-swagger-ui/src/axum.rs index 5edd8656..5315fc3f 100644 --- a/utoipa-swagger-ui/src/axum.rs +++ b/utoipa-swagger-ui/src/axum.rs @@ -3,16 +3,14 @@ use std::sync::Arc; use axum::{ - body::HttpBody, extract::Path, http::StatusCode, response::IntoResponse, routing, Extension, - Json, Router, + extract::Path, http::StatusCode, response::IntoResponse, routing, Extension, Json, Router, }; use crate::{ApiDoc, Config, SwaggerUi, Url}; -impl From for Router +impl From for Router where S: Clone + Send + Sync + 'static, - B: HttpBody + Send + 'static, { fn from(swagger_ui: SwaggerUi) -> Self { let urls_capacity = swagger_ui.urls.len(); @@ -20,7 +18,7 @@ where let (router, urls) = swagger_ui.urls.into_iter().fold( ( - Router::::new(), + Router::::new(), Vec::::with_capacity(urls_capacity + external_urls_capacity), ), |router_and_urls, (url, openapi)| { @@ -58,13 +56,12 @@ where } } -fn add_api_doc_to_urls( - router_and_urls: (Router, Vec>), +fn add_api_doc_to_urls( + router_and_urls: (Router, Vec>), url: (Url<'static>, ApiDoc), -) -> (Router, Vec>) +) -> (Router, Vec>) where S: Clone + Send + Sync + 'static, - B: HttpBody + Send + 'static, { let (router, mut urls) = router_and_urls; let (url, openapi) = url; diff --git a/utoipa-swagger-ui/src/lib.rs b/utoipa-swagger-ui/src/lib.rs index 56957dd4..25f57932 100644 --- a/utoipa-swagger-ui/src/lib.rs +++ b/utoipa-swagger-ui/src/lib.rs @@ -92,19 +92,18 @@ //! Setup Router to serve Swagger UI with **`axum`** framework. See full implementation of how to serve //! Swagger UI with axum from [examples](https://github.com/juhaku/utoipa/tree/master/examples/todo-axum). //!```no_run -//! # use axum::{routing, Router, body::HttpBody}; +//! # use axum::{routing, Router}; //! # use utoipa_swagger_ui::SwaggerUi; //! # use utoipa::OpenApi; //!# #[derive(OpenApi)] //!# #[openapi()] //!# struct ApiDoc; //!# -//!# fn inner() +//!# fn inner() //!# where -//!# B: HttpBody + Send + 'static, //!# S: Clone + Send + Sync + 'static, //!# { -//! let app = Router::::new() +//! let app = Router::::new() //! .merge(SwaggerUi::new("/swagger-ui") //! .url("/api-docs/openapi.json", ApiDoc::openapi())); //!# }