From 6de881c27d526a73562ff7dbd09b56a870092af8 Mon Sep 17 00:00:00 2001 From: Guillermo Lloret Talavera Date: Tue, 19 Sep 2023 19:43:39 +0200 Subject: [PATCH 1/5] Add handle_error function to ServiceExt trait --- axum/src/service_ext.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/axum/src/service_ext.rs b/axum/src/service_ext.rs index e603d65f16..b54f43be0c 100644 --- a/axum/src/service_ext.rs +++ b/axum/src/service_ext.rs @@ -1,3 +1,4 @@ +use crate::error_handling::HandleError; #[cfg(feature = "tokio")] use crate::extract::connect_info::IntoMakeServiceWithConnectInfo; use crate::routing::IntoMakeService; @@ -30,6 +31,15 @@ pub trait ServiceExt: Service + Sized { /// [`ConnectInfo`]: crate::extract::connect_info::ConnectInfo #[cfg(feature = "tokio")] fn into_make_service_with_connect_info(self) -> IntoMakeServiceWithConnectInfo; + + /// Convert this service into a [`HandleError`], that will handle errors + /// by converting them into responses. + /// + /// See ["error handling model"] for more details. + /// + /// [`HandleError`]: crate::error_handling::HandleError + /// ["error handling model"]: crate::error_handling#axums-error-handling-model + fn handle_error(self, f: F) -> HandleError; } impl ServiceExt for S @@ -44,4 +54,8 @@ where fn into_make_service_with_connect_info(self) -> IntoMakeServiceWithConnectInfo { IntoMakeServiceWithConnectInfo::new(self) } + + fn handle_error(self, f: F) -> HandleError { + HandleError::new(self, f) + } } From c3d23600b7f23740f9846f1526b2789da29f8fa7 Mon Sep 17 00:00:00 2001 From: Guillermo Lloret Talavera Date: Tue, 19 Sep 2023 21:13:29 +0200 Subject: [PATCH 2/5] Add handle_error (ServiceExt) test --- axum/src/routing/tests/handle_error.rs | 13 +++++++++++++ axum/src/routing/tests/mod.rs | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/axum/src/routing/tests/handle_error.rs b/axum/src/routing/tests/handle_error.rs index a1af97af70..5257f99c79 100644 --- a/axum/src/routing/tests/handle_error.rs +++ b/axum/src/routing/tests/handle_error.rs @@ -95,3 +95,16 @@ async fn handler_multiple_methods_last() { let res = client.get("/").send().await; assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT); } + +#[crate::test] +async fn handler_service_ext() { + let fallible_service = tower::service_fn(|_| async { Err::<(), ()>(()) }); + let handle_error_service = fallible_service.handle_error(|_| async { StatusCode::INTERNAL_SERVER_ERROR }); + + let app = Router::new().route("/", get_service(handle_error_service)); + + let client = TestClient::new(app); + + let res = client.get("/").send().await; + assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); +} diff --git a/axum/src/routing/tests/mod.rs b/axum/src/routing/tests/mod.rs index f27ba0eb61..9db43c6cd7 100644 --- a/axum/src/routing/tests/mod.rs +++ b/axum/src/routing/tests/mod.rs @@ -12,7 +12,7 @@ use crate::{ tracing_helpers::{capture_tracing, TracingEvent}, *, }, - BoxError, Extension, Json, Router, + BoxError, Extension, Json, Router, ServiceExt, }; use axum_core::extract::Request; use futures_util::stream::StreamExt; @@ -30,7 +30,7 @@ use std::{ task::{Context, Poll}, time::Duration, }; -use tower::{service_fn, util::MapResponseLayer, ServiceExt}; +use tower::{service_fn, util::MapResponseLayer, ServiceExt as TowerServiceExt}; use tower_http::{ limit::RequestBodyLimitLayer, timeout::TimeoutLayer, validate_request::ValidateRequestHeaderLayer, From a8a6949a71c04d36b8fc5f110efd449950810000 Mon Sep 17 00:00:00 2001 From: Guillermo Lloret Talavera Date: Wed, 20 Sep 2023 13:40:20 +0200 Subject: [PATCH 3/5] Move handle_error implementation to ServiceExt --- axum/src/service_ext.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/axum/src/service_ext.rs b/axum/src/service_ext.rs index b54f43be0c..1b49f244b6 100644 --- a/axum/src/service_ext.rs +++ b/axum/src/service_ext.rs @@ -39,7 +39,9 @@ pub trait ServiceExt: Service + Sized { /// /// [`HandleError`]: crate::error_handling::HandleError /// ["error handling model"]: crate::error_handling#axums-error-handling-model - fn handle_error(self, f: F) -> HandleError; + fn handle_error(self, f: F) -> HandleError { + HandleError::new(self, f) + } } impl ServiceExt for S @@ -54,8 +56,4 @@ where fn into_make_service_with_connect_info(self) -> IntoMakeServiceWithConnectInfo { IntoMakeServiceWithConnectInfo::new(self) } - - fn handle_error(self, f: F) -> HandleError { - HandleError::new(self, f) - } } From 971d3489c697e47b435d6563e4d3258b6978a647 Mon Sep 17 00:00:00 2001 From: Guillermo Lloret Talavera Date: Fri, 29 Sep 2023 13:42:31 +0200 Subject: [PATCH 4/5] Update CHANGELOG --- axum/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md index 57474c5303..86101119c2 100644 --- a/axum/CHANGELOG.md +++ b/axum/CHANGELOG.md @@ -66,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **added:** Implement `IntoResponse` for `(R,) where R: IntoResponse` ([#2143]) - **changed:** For SSE, add space between field and value for compatibility ([#2149]) - **added:** Add `NestedPath` extractor ([#1924]) +- **added:** Add `handle_error` function to existing `ServiceExt` trait ([#2235]) [#1664]: https://github.com/tokio-rs/axum/pull/1664 [#1751]: https://github.com/tokio-rs/axum/pull/1751 @@ -86,6 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2140]: https://github.com/tokio-rs/axum/pull/2140 [#2143]: https://github.com/tokio-rs/axum/pull/2143 [#2149]: https://github.com/tokio-rs/axum/pull/2149 +[#2235]: https://github.com/tokio-rs/axum/pull/2235 # 0.6.17 (25. April, 2023) From ae54f65a545e67644790a7c8c26d85a207c793ff Mon Sep 17 00:00:00 2001 From: Guillermo Lloret Talavera Date: Fri, 29 Sep 2023 13:59:00 +0200 Subject: [PATCH 5/5] Fix format cargo fmt --- axum/src/routing/tests/handle_error.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/axum/src/routing/tests/handle_error.rs b/axum/src/routing/tests/handle_error.rs index 5257f99c79..9b81a20f1d 100644 --- a/axum/src/routing/tests/handle_error.rs +++ b/axum/src/routing/tests/handle_error.rs @@ -99,7 +99,8 @@ async fn handler_multiple_methods_last() { #[crate::test] async fn handler_service_ext() { let fallible_service = tower::service_fn(|_| async { Err::<(), ()>(()) }); - let handle_error_service = fallible_service.handle_error(|_| async { StatusCode::INTERNAL_SERVER_ERROR }); + let handle_error_service = + fallible_service.handle_error(|_| async { StatusCode::INTERNAL_SERVER_ERROR }); let app = Router::new().route("/", get_service(handle_error_service));