Skip to content

Commit

Permalink
Axum 0.7 bindings (#807)
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
Libbum authored Nov 28, 2023
1 parent 048d898 commit 93dfaf1
Show file tree
Hide file tree
Showing 14 changed files with 37 additions and 45 deletions.
4 changes: 2 additions & 2 deletions examples/todo-axum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
8 changes: 5 additions & 3 deletions examples/todo-axum/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion utoipa-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
2 changes: 1 addition & 1 deletion utoipa-rapidoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
6 changes: 3 additions & 3 deletions utoipa-rapidoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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::<S, B>::new()
let app = Router::<S>::new()
.merge(RapiDoc::with_openapi("/rapidoc", ApiDoc::openapi()));
```

Expand Down
13 changes: 5 additions & 8 deletions utoipa-rapidoc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<S, B>()
//! # fn inner<S>()
//! # where
//! # B: HttpBody + Send + 'static,
//! # S: Clone + Send + Sync + 'static,
//! # {
//!
//! let app = Router::<S, B>::new()
//! let app = Router::<S>::new()
//! .merge(RapiDoc::with_openapi("/rapidoc", ApiDoc::openapi()));
//! # }
//! ```
Expand Down Expand Up @@ -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<R, B> From<RapiDoc<'_, '_, '_>> for Router<R, B>
impl<R> From<RapiDoc<'_, '_, '_>> for Router<R>
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::<R, B>::new().route(value.path, routing::get(move || async { Html(html) }));
Router::<R>::new().route(value.path, routing::get(move || async { Html(html) }));

if let Some(openapi) = openapi {
router = router.route(
Expand Down
2 changes: 1 addition & 1 deletion utoipa-redoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
6 changes: 3 additions & 3 deletions utoipa-redoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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::<S, B>::new()
let app = Router::<S>::new()
.merge(Redoc::with_url("/redoc", ApiDoc::openapi()));
```

Expand Down
6 changes: 2 additions & 4 deletions utoipa-redoc/src/axum.rs
Original file line number Diff line number Diff line change
@@ -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<Redoc<'s, 'u, S>> for Router<R, B>
impl<'s, 'u, S: Spec, R> From<Redoc<'s, 'u, S>> for Router<R>
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::<R, B>::new().route(value.url, routing::get(move || async { Html(html) }))
Router::<R>::new().route(value.url, routing::get(move || async { Html(html) }))
}
}
7 changes: 3 additions & 4 deletions utoipa-redoc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<S, B>()
//! # fn inner<S>()
//! # where
//! # B: HttpBody + Send + 'static,
//! # S: Clone + Send + Sync + 'static,
//! # {
//!
//! let app = Router::<S, B>::new()
//! let app = Router::<S>::new()
//! .merge(Redoc::with_url("/redoc", ApiDoc::openapi()));
//! # }
//! ```
Expand Down
2 changes: 1 addition & 1 deletion utoipa-swagger-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
2 changes: 1 addition & 1 deletion utoipa-swagger-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 6 additions & 9 deletions utoipa-swagger-ui/src/axum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@
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<S, B> From<SwaggerUi> for Router<S, B>
impl<S> From<SwaggerUi> for Router<S>
where
S: Clone + Send + Sync + 'static,
B: HttpBody + Send + 'static,
{
fn from(swagger_ui: SwaggerUi) -> Self {
let urls_capacity = swagger_ui.urls.len();
let external_urls_capacity = swagger_ui.external_urls.len();

let (router, urls) = swagger_ui.urls.into_iter().fold(
(
Router::<S, B>::new(),
Router::<S>::new(),
Vec::<Url>::with_capacity(urls_capacity + external_urls_capacity),
),
|router_and_urls, (url, openapi)| {
Expand Down Expand Up @@ -58,13 +56,12 @@ where
}
}

fn add_api_doc_to_urls<S, B>(
router_and_urls: (Router<S, B>, Vec<Url<'static>>),
fn add_api_doc_to_urls<S>(
router_and_urls: (Router<S>, Vec<Url<'static>>),
url: (Url<'static>, ApiDoc),
) -> (Router<S, B>, Vec<Url<'static>>)
) -> (Router<S>, Vec<Url<'static>>)
where
S: Clone + Send + Sync + 'static,
B: HttpBody + Send + 'static,
{
let (router, mut urls) = router_and_urls;
let (url, openapi) = url;
Expand Down
7 changes: 3 additions & 4 deletions utoipa-swagger-ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<S, B>()
//!# fn inner<S>()
//!# where
//!# B: HttpBody + Send + 'static,
//!# S: Clone + Send + Sync + 'static,
//!# {
//! let app = Router::<S, B>::new()
//! let app = Router::<S>::new()
//! .merge(SwaggerUi::new("/swagger-ui")
//! .url("/api-docs/openapi.json", ApiDoc::openapi()));
//!# }
Expand Down

0 comments on commit 93dfaf1

Please sign in to comment.