From 78656ebb4a925329dc19c17a4dbef31d7551d4f5 Mon Sep 17 00:00:00 2001 From: Mohamed Macow <58916277+darth-raijin@users.noreply.github.com> Date: Fri, 21 Nov 2025 23:17:24 +0100 Subject: [PATCH 1/6] docs: Clarify `route_layer` does not apply middleware to the fallback handler (#3567) --- axum/src/docs/method_routing/route_layer.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/axum/src/docs/method_routing/route_layer.md b/axum/src/docs/method_routing/route_layer.md index 501b5517..b045d100 100644 --- a/axum/src/docs/method_routing/route_layer.md +++ b/axum/src/docs/method_routing/route_layer.md @@ -1,8 +1,7 @@ Apply a [`tower::Layer`] to the router that will only run if the request matches a route. -Note that the middleware is only applied to existing routes. So you have to -first add your routes (and / or fallback) and then call `route_layer` +Note that the middleware is only applied to existing routes. First add your routes and then call `route_layer` afterwards. Additional routes added after `route_layer` is called will not have the middleware added. From 816407a8166491217168890ee96856469c3b424c Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 22 Nov 2025 20:09:42 +0100 Subject: [PATCH 2/6] Fix integer underflow in `try_range_response` for empty files (#3566) --- Cargo.lock | 1 + axum-extra/Cargo.toml | 1 + axum-extra/src/response/file_stream.rs | 52 ++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 995b6eb0..49f35ebc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,6 +390,7 @@ dependencies = [ "serde_html_form", "serde_json", "serde_path_to_error", + "tempfile", "tokio", "tokio-stream", "tokio-util", diff --git a/axum-extra/Cargo.toml b/axum-extra/Cargo.toml index 96d48bd7..219d073c 100644 --- a/axum-extra/Cargo.toml +++ b/axum-extra/Cargo.toml @@ -120,6 +120,7 @@ hyper = "1.0.0" reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] } serde = { version = "1.0.221", features = ["derive"] } serde_json = "1.0.71" +tempfile = "3.23.0" tokio = { version = "1.14", features = ["full"] } tower = { version = "0.5.2", features = ["util"] } tower-http = { version = "0.6.0", features = ["map-response-body", "timeout"] } diff --git a/axum-extra/src/response/file_stream.rs b/axum-extra/src/response/file_stream.rs index da9d0d78..c36fe61b 100644 --- a/axum-extra/src/response/file_stream.rs +++ b/axum-extra/src/response/file_stream.rs @@ -191,6 +191,10 @@ where let metadata = file.metadata().await?; let total_size = metadata.len(); + if total_size == 0 { + return Ok((StatusCode::RANGE_NOT_SATISFIABLE, "Range Not Satisfiable").into_response()); + } + if end == 0 { end = total_size - 1; } @@ -596,4 +600,52 @@ mod tests { } Some((start, end)) } + + #[tokio::test] + async fn response_range_empty_file() -> Result<(), Box> { + let file = tempfile::NamedTempFile::new()?; + file.as_file().set_len(0)?; + let path = file.path().to_owned(); + + let app = Router::new().route( + "/range_empty", + get(move |headers: HeaderMap| { + let path = path.clone(); + async move { + let range_header = headers + .get(header::RANGE) + .and_then(|value| value.to_str().ok()); + + let (start, end) = if let Some(range) = range_header { + if let Some(range) = parse_range_header(range) { + range + } else { + return (StatusCode::RANGE_NOT_SATISFIABLE, "Invalid Range") + .into_response(); + } + } else { + (0, 0) + }; + + FileStream::>::try_range_response(path, start, end) + .await + .unwrap_or_else(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response()) + } + }), + ); + + let response = app + .oneshot( + Request::builder() + .uri("/range_empty") + .header(header::RANGE, "bytes=0-") + .body(Body::empty()) + .unwrap(), + ) + .await + .unwrap(); + + assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE); + Ok(()) + } } From f51f3ba4366e1060206efc41fde1227055164c45 Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Mon, 24 Nov 2025 21:34:46 +0100 Subject: [PATCH 3/6] axum-extra: Add trailing newline to pretty JSON response (#3526) --- axum-extra/src/response/erased_json.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/axum-extra/src/response/erased_json.rs b/axum-extra/src/response/erased_json.rs index 76c7390e..aa554a7e 100644 --- a/axum-extra/src/response/erased_json.rs +++ b/axum-extra/src/response/erased_json.rs @@ -57,7 +57,10 @@ impl ErasedJson { pub fn pretty(val: T) -> Self { let mut bytes = BytesMut::with_capacity(128); let result = match serde_json::to_writer_pretty((&mut bytes).writer(), &val) { - Ok(()) => Ok(bytes.freeze()), + Ok(()) => { + bytes.put_u8(b'\n'); + Ok(bytes.freeze()) + } Err(e) => Err(Arc::new(e)), }; Self(result) From f5804aa6a13f8af1ae1a8998b872b300b0859d81 Mon Sep 17 00:00:00 2001 From: Brad Dunbar Date: Tue, 2 Dec 2025 18:24:27 -0500 Subject: [PATCH 4/6] SecondElementIs: Correct a small inconsistency (#3559) --- axum-extra/src/routing/typed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum-extra/src/routing/typed.rs b/axum-extra/src/routing/typed.rs index 909a0419..06652092 100644 --- a/axum-extra/src/routing/typed.rs +++ b/axum-extra/src/routing/typed.rs @@ -320,7 +320,7 @@ where /// Utility trait used with [`RouterExt`] to ensure the second element of a tuple type is a /// given type. /// -/// If you see it in type errors it's most likely because the second argument to your handler doesn't +/// If you see it in type errors it's most likely because the first argument to your handler doesn't /// implement [`TypedPath`]. /// /// You normally shouldn't have to use this trait directly. From 287c674b65fa363fa8e60a5b2de7502dfda0decc Mon Sep 17 00:00:00 2001 From: tottoto Date: Sat, 11 Oct 2025 18:22:51 +0900 Subject: [PATCH 5/6] axum-extra: Make typed-routing feature enable routing feature (#3514) --- axum-extra/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/axum-extra/Cargo.toml b/axum-extra/Cargo.toml index 219d073c..3ebebf9f 100644 --- a/axum-extra/Cargo.toml +++ b/axum-extra/Cargo.toml @@ -63,6 +63,7 @@ query = [ tracing = ["axum-core/tracing", "axum/tracing", "dep:tracing"] typed-header = ["dep:headers"] typed-routing = [ + "routing", "dep:axum-macros", "dep:percent-encoding", "dep:serde_core", From d07863f97d2649c414d2cdd162d1a10750e29a25 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 20 Dec 2025 14:14:20 +0100 Subject: [PATCH 6/6] Release axum v0.8.8 and axum-extra v0.12.3 --- Cargo.lock | 4 ++-- axum-extra/CHANGELOG.md | 10 ++++++++++ axum-extra/Cargo.toml | 4 ++-- axum/CHANGELOG.md | 6 ++++++ axum/Cargo.toml | 2 +- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49f35ebc..72ece474 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,7 +292,7 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.7" +version = "0.8.8" dependencies = [ "anyhow", "axum-core", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.2" +version = "0.12.3" dependencies = [ "axum", "axum-core", diff --git a/axum-extra/CHANGELOG.md b/axum-extra/CHANGELOG.md index 7213baf0..3c30c566 100644 --- a/axum-extra/CHANGELOG.md +++ b/axum-extra/CHANGELOG.md @@ -5,6 +5,16 @@ 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.3 + +- **changed:** Make the `typed-routing` feature enable the `routing` feature ([#3514]) +- **changed:** Add trailing newline to `ErasedJson::pretty` response bodies ([#3526]) +- **fixed:** Fix integer underflow in `FileStream::try_range_response` for empty files ([#3566]) + +[#3514]: https://github.com/tokio-rs/axum/pull/3514 +[#3526]: https://github.com/tokio-rs/axum/pull/3526 +[#3566]: https://github.com/tokio-rs/axum/pull/3566 + # 0.12.2 - Make it easier to visually scan for default features ([#3550]) diff --git a/axum-extra/Cargo.toml b/axum-extra/Cargo.toml index 3ebebf9f..be652623 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.2" +version = "0.12.3" [features] default = ["tracing"] @@ -90,7 +90,7 @@ tower-layer = "0.3" tower-service = "0.3" # optional dependencies -axum = { path = "../axum", version = "0.8.7", default-features = false, optional = true } +axum = { path = "../axum", version = "0.8.8", 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 1602cd34..c0e9c470 100644 --- a/axum/CHANGELOG.md +++ b/axum/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](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# 0.8.8 + +- Clarify documentation for `Router::route_layer` ([#3567]) + +[#3567]: https://github.com/tokio-rs/axum/pull/3567 + # 0.8.7 - Relax implicit `Send` / `Sync` bounds on `RouterAsService`, `RouterIntoService` ([#3555]) diff --git a/axum/Cargo.toml b/axum/Cargo.toml index 0df7e8e2..770bd0c3 100644 --- a/axum/Cargo.toml +++ b/axum/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "axum" -version = "0.8.7" # remember to bump the version that axum-extra depends on +version = "0.8.8" # 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"