From fe607e6dcf5dab2cdf8e2d5f8d8be26ae0b08ce0 Mon Sep 17 00:00:00 2001 From: Italo Maia Date: Sun, 26 Oct 2025 23:35:01 +0100 Subject: [PATCH 1/6] Fixes wording typo (#3540) --- axum/src/docs/routing/with_state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/src/docs/routing/with_state.md b/axum/src/docs/routing/with_state.md index 197741cf55..1c25178d0c 100644 --- a/axum/src/docs/routing/with_state.md +++ b/axum/src/docs/routing/with_state.md @@ -157,7 +157,7 @@ axum::serve(listener, final_router).await.unwrap(); # }; ``` -This why this returning `Router` after calling `with_state` doesn't +This is why returning `Router` after calling `with_state` doesn't work: ```rust,compile_fail From 6d5e6d578a2c5cd517f92af211c36f4eeb213e9d Mon Sep 17 00:00:00 2001 From: Brad Dunbar Date: Thu, 30 Oct 2025 08:40:00 -0400 Subject: [PATCH 2/6] Use extensions directly in from_request_parts (#3542) --- axum-extra/src/extract/cached.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/axum-extra/src/extract/cached.rs b/axum-extra/src/extract/cached.rs index 64b4c3056f..0b299d2b9c 100644 --- a/axum-extra/src/extract/cached.rs +++ b/axum-extra/src/extract/cached.rs @@ -1,4 +1,4 @@ -use axum::extract::{Extension, FromRequestParts}; +use axum::extract::FromRequestParts; use http::request::Parts; /// Cache results of other extractors. @@ -88,13 +88,12 @@ where type Rejection = T::Rejection; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { - match Extension::>::from_request_parts(parts, state).await { - Ok(Extension(CachedEntry(value))) => Ok(Self(value)), - Err(_) => { - let value = T::from_request_parts(parts, state).await?; - parts.extensions.insert(CachedEntry(value.clone())); - Ok(Self(value)) - } + if let Some(value) = parts.extensions.get::>() { + Ok(Self(value.0.clone())) + } else { + let value = T::from_request_parts(parts, state).await?; + parts.extensions.insert(CachedEntry(value.clone())); + Ok(Self(value)) } } } From a05920c906fb5fe3c5b734f80465a3a6f06948f1 Mon Sep 17 00:00:00 2001 From: Lyra Naeseth Date: Mon, 10 Nov 2025 01:41:04 -0800 Subject: [PATCH 3/6] Make it easier to visually scan for default features (#3550) --- axum-extra/src/lib.rs | 48 +++++++++++++++++++++---------------------- axum/src/lib.rs | 26 +++++++++++------------ 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/axum-extra/src/lib.rs b/axum-extra/src/lib.rs index 743a926870..9ef98747fb 100644 --- a/axum-extra/src/lib.rs +++ b/axum-extra/src/lib.rs @@ -9,30 +9,30 @@ //! //! Name | Description | Default? //! ---|---|--- -//! `async-read-body` | Enables the [`AsyncReadBody`](crate::body::AsyncReadBody) body | No -//! `attachment` | Enables the [`Attachment`](crate::response::Attachment) response | No -//! `cached` | Enables the [`Cached`](crate::extract::Cached) extractor | No -//! `cookie` | Enables the [`CookieJar`](crate::extract::CookieJar) extractor | No -//! `cookie-private` | Enables the [`PrivateCookieJar`](crate::extract::PrivateCookieJar) extractor | No -//! `cookie-signed` | Enables the [`SignedCookieJar`](crate::extract::SignedCookieJar) extractor | No -//! `cookie-key-expansion` | Enables the [`Key::derive_from`](crate::extract::cookie::Key::derive_from) method | No -//! `erased-json` | Enables the [`ErasedJson`](crate::response::ErasedJson) response | No -//! `error-response` | Enables the [`InternalServerError`](crate::response::InternalServerError) response | No -//! `form` | Enables the [`Form`](crate::extract::Form) extractor | No -//! `handler` | Enables the [handler] utilities | No -//! `json-deserializer` | Enables the [`JsonDeserializer`](crate::extract::JsonDeserializer) extractor | No -//! `json-lines` | Enables the [`JsonLines`](crate::extract::JsonLines) extractor and response | No -//! `middleware` | Enables the [middleware] utilities | No -//! `multipart` | Enables the [`Multipart`](crate::extract::Multipart) extractor | No -//! `optional-path` | Enables the [`OptionalPath`](crate::extract::OptionalPath) extractor | No -//! `protobuf` | Enables the [`Protobuf`](crate::protobuf::Protobuf) extractor and response | No -//! `query` | Enables the [`Query`](crate::extract::Query) extractor | No -//! `routing` | Enables the [routing] utilities | No -//! `tracing` | Log rejections from built-in extractors | Yes -//! `typed-routing` | Enables the [`TypedPath`](crate::routing::TypedPath) routing utilities | No -//! `typed-header` | Enables the [`TypedHeader`] extractor and response | No -//! `file-stream` | Enables the [`FileStream`](crate::response::FileStream) response | No -//! `with-rejection` | Enables the [`WithRejection`](crate::extract::WithRejection) extractor | No +//! `async-read-body` | Enables the [`AsyncReadBody`](crate::body::AsyncReadBody) body | +//! `attachment` | Enables the [`Attachment`](crate::response::Attachment) response | +//! `cached` | Enables the [`Cached`](crate::extract::Cached) extractor | +//! `cookie` | Enables the [`CookieJar`](crate::extract::CookieJar) extractor | +//! `cookie-private` | Enables the [`PrivateCookieJar`](crate::extract::PrivateCookieJar) extractor | +//! `cookie-signed` | Enables the [`SignedCookieJar`](crate::extract::SignedCookieJar) extractor | +//! `cookie-key-expansion` | Enables the [`Key::derive_from`](crate::extract::cookie::Key::derive_from) method | +//! `erased-json` | Enables the [`ErasedJson`](crate::response::ErasedJson) response | +//! `error-response` | Enables the [`InternalServerError`](crate::response::InternalServerError) response | +//! `form` | Enables the [`Form`](crate::extract::Form) extractor | +//! `handler` | Enables the [handler] utilities | +//! `json-deserializer` | Enables the [`JsonDeserializer`](crate::extract::JsonDeserializer) extractor | +//! `json-lines` | Enables the [`JsonLines`](crate::extract::JsonLines) extractor and response | +//! `middleware` | Enables the [middleware] utilities | +//! `multipart` | Enables the [`Multipart`](crate::extract::Multipart) extractor | +//! `optional-path` | Enables the [`OptionalPath`](crate::extract::OptionalPath) extractor | +//! `protobuf` | Enables the [`Protobuf`](crate::protobuf::Protobuf) extractor and response | +//! `query` | Enables the [`Query`](crate::extract::Query) extractor | +//! `routing` | Enables the [routing] utilities | +//! `tracing` | Log rejections from built-in extractors | +//! `typed-routing` | Enables the [`TypedPath`](crate::routing::TypedPath) routing utilities and the `routing` feature. | +//! `typed-header` | Enables the [`TypedHeader`] extractor and response | +//! `file-stream` | Enables the [`FileStream`](crate::response::FileStream) response | +//! `with-rejection` | Enables the [`WithRejection`](crate::extract::WithRejection) extractor | //! //! [`axum`]: https://crates.io/crates/axum diff --git a/axum/src/lib.rs b/axum/src/lib.rs index 3800db5dea..a7ed196301 100644 --- a/axum/src/lib.rs +++ b/axum/src/lib.rs @@ -381,19 +381,19 @@ //! //! Name | Description | Default? //! ---|---|--- -//! `http1` | Enables hyper's `http1` feature | Yes -//! `http2` | Enables hyper's `http2` feature | No -//! `json` | Enables the [`Json`] type and some similar convenience functionality | Yes -//! `macros` | Enables optional utility macros | No -//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | Yes -//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No -//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | Yes -//! `tokio` | Enables `tokio` as a dependency and `axum::serve`, `SSE` and `extract::connect_info` types. | Yes -//! `tower-log` | Enables `tower`'s `log` feature | Yes -//! `tracing` | Log rejections from built-in extractors | Yes -//! `ws` | Enables WebSockets support via [`extract::ws`] | No -//! `form` | Enables the `Form` extractor | Yes -//! `query` | Enables the `Query` extractor | Yes +//! `http1` | Enables hyper's `http1` feature | +//! `http2` | Enables hyper's `http2` feature | +//! `json` | Enables the [`Json`] type and some similar convenience functionality | +//! `macros` | Enables optional utility macros | +//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | +//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | +//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | +//! `tokio` | Enables `tokio` as a dependency and `axum::serve`, `SSE` and `extract::connect_info` types. | +//! `tower-log` | Enables `tower`'s `log` feature | +//! `tracing` | Log rejections from built-in extractors | +//! `ws` | Enables WebSockets support via [`extract::ws`] | +//! `form` | Enables the `Form` extractor | +//! `query` | Enables the `Query` extractor | //! //! [`MatchedPath`]: crate::extract::MatchedPath //! [`Multipart`]: crate::extract::Multipart From 4fc3faa0b4d82db870d8daaf49978da960bcfc42 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Fri, 14 Nov 2025 10:48:07 +0100 Subject: [PATCH 4/6] Relax implicit Send / Sync bounds (#3555) --- axum/src/routing/mod.rs | 8 ++++++-- axum/src/serve/mod.rs | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/axum/src/routing/mod.rs b/axum/src/routing/mod.rs index 90238c1037..deeeadc096 100644 --- a/axum/src/routing/mod.rs +++ b/axum/src/routing/mod.rs @@ -592,7 +592,7 @@ where /// See [`Router::as_service`] for more details. pub struct RouterAsService<'a, B, S = ()> { router: &'a mut Router, - _marker: PhantomData, + _marker: PhantomData, } impl Service> for RouterAsService<'_, B, ()> @@ -631,7 +631,7 @@ where /// See [`Router::into_service`] for more details. pub struct RouterIntoService { router: Router, - _marker: PhantomData, + _marker: PhantomData, } impl Clone for RouterIntoService @@ -800,4 +800,8 @@ fn traits() { use crate::test_helpers::*; assert_send::>(); assert_sync::>(); + assert_send::>(); + assert_sync::>(); + assert_send::>(); + assert_sync::>(); } diff --git a/axum/src/serve/mod.rs b/axum/src/serve/mod.rs index b5b8b573b9..3f2a39fa7d 100644 --- a/axum/src/serve/mod.rs +++ b/axum/src/serve/mod.rs @@ -114,7 +114,7 @@ where pub struct Serve { listener: L, make_service: M, - _marker: PhantomData, + _marker: PhantomData S>, } #[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))] @@ -239,7 +239,7 @@ pub struct WithGracefulShutdown { listener: L, make_service: M, signal: F, - _marker: PhantomData, + _marker: PhantomData S>, } #[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))] From 8f1545adecc86036ed9c8f252edcc099f7016103 Mon Sep 17 00:00:00 2001 From: Andrii Mishkovskyi <548482+mishok13@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:47:58 +0100 Subject: [PATCH 5/6] Fix typo in extractors guide (#3554) --- axum/src/docs/extract.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/axum/src/docs/extract.md b/axum/src/docs/extract.md index 4659d908d6..f65b55a859 100644 --- a/axum/src/docs/extract.md +++ b/axum/src/docs/extract.md @@ -606,8 +606,8 @@ For more details, including how to disable this limit, see [`DefaultBodyLimit`]. # Wrapping extractors -If you want write an extractor that generically wraps another extractor (that -may or may not consume the request body) you should implement both +If you want to write an extractor that generically wraps another extractor +(that may or may not consume the request body) you should implement both [`FromRequest`] and [`FromRequestParts`]: ```rust From 4404f27cea206b0dca63637b1c76dff23772a5cc Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Fri, 14 Nov 2025 20:44:55 +0100 Subject: [PATCH 6/6] Release axum v0.8.7 and axum-extra v0.12.2 --- Cargo.lock | 4 ++-- axum-extra/CHANGELOG.md | 6 ++++++ axum-extra/Cargo.toml | 4 ++-- axum/CHANGELOG.md | 9 +++++++++ axum/Cargo.toml | 2 +- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0996f88c41..995b6eb03b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,7 +292,7 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.6" +version = "0.8.7" dependencies = [ "anyhow", "axum-core", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.1" +version = "0.12.2" dependencies = [ "axum", "axum-core", diff --git a/axum-extra/CHANGELOG.md b/axum-extra/CHANGELOG.md index a06df8b429..7213baf012 100644 --- a/axum-extra/CHANGELOG.md +++ b/axum-extra/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning]. +# 0.12.2 + +- Make it easier to visually scan for default features ([#3550]) + +[#3550]: https://github.com/tokio-rs/axum/pull/3550 + # 0.12.1 This release contains no changes in code, only a small `Cargo.toml` fix for diff --git a/axum-extra/Cargo.toml b/axum-extra/Cargo.toml index ebd0e1b327..96d48bd707 100644 --- a/axum-extra/Cargo.toml +++ b/axum-extra/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" name = "axum-extra" readme = "README.md" repository = "https://github.com/tokio-rs/axum" -version = "0.12.1" +version = "0.12.2" [features] default = ["tracing"] @@ -89,7 +89,7 @@ tower-layer = "0.3" tower-service = "0.3" # optional dependencies -axum = { path = "../axum", version = "0.8.4", default-features = false, optional = true } +axum = { path = "../axum", version = "0.8.7", default-features = false, optional = true } axum-macros = { path = "../axum-macros", version = "0.5.0", optional = true } cookie = { package = "cookie", version = "0.18.0", features = ["percent-encode"], optional = true } fastrand = { version = "2.1.0", optional = true } diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md index 92d46088e3..1602cd341a 100644 --- a/axum/CHANGELOG.md +++ b/axum/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# 0.8.7 + +- Relax implicit `Send` / `Sync` bounds on `RouterAsService`, `RouterIntoService` ([#3555]) +- Make it easier to visually scan for default features ([#3550]) +- Fix some documentation typos + +[#3550]: https://github.com/tokio-rs/axum/pull/3550 +[#3555]: https://github.com/tokio-rs/axum/pull/3555 + # 0.8.6 Released without changes to fix docs.rs build. diff --git a/axum/Cargo.toml b/axum/Cargo.toml index 007738eb2c..0df7e8e21e 100644 --- a/axum/Cargo.toml +++ b/axum/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "axum" -version = "0.8.6" # remember to bump the version that axum-extra depends on +version = "0.8.7" # remember to bump the version that axum-extra depends on categories = ["asynchronous", "network-programming", "web-programming::http-server"] description = "Web framework that focuses on ergonomics and modularity" edition = "2021"