From 080c5dcb1f971356f3203c544e3027f18bb0b9d1 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Mon, 1 Nov 2021 22:27:04 +0100 Subject: [PATCH] Remove `Sync` requirement from response bodies As we learned [in Tonic] bodies don't need to be `Sync` because they can only be polled from one thread at a time. This changes axum's bodies to no longer require `Sync` and makes `BoxBody` an alias for `UnsyncBoxBody`. [in Tonic]: https://github.com/hyperium/tonic/issues/117 --- CHANGELOG.md | 4 ++++ Cargo.toml | 4 ++-- src/body.rs | 6 +++--- src/error_handling/mod.rs | 8 ++++---- src/extract/extractor_middleware.rs | 4 ++-- src/handler/mod.rs | 4 ++-- src/response/headers.rs | 4 ++-- src/response/mod.rs | 12 ++++++------ src/routing/method_not_allowed.rs | 2 +- src/routing/mod.rs | 8 ++++---- src/routing/not_found.rs | 2 +- src/routing/service_method_routing.rs | 4 ++-- 12 files changed, 33 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67a1e62ee91..337941c0fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 thus wasn't necessary - **breaking:** Vendor `AddExtensionLayer` and `AddExtension` to reduce public dependencies + - **breaking:** `body::BoxBody` is now a type alias for + `http_body::combinators::UnsyncBoxBody` and thus is no longer `Sync`. This + is because bodies are streams and requiring streams to be `Sync` is + unnecessary. - Routing: - Big internal refactoring of routing leading to several improvements ([#363]) - **added:** Wildcard routes like `.route("/api/users/*rest", service)` are now supported. diff --git a/Cargo.toml b/Cargo.toml index 9adbb91b09e..d4acebe5847 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,8 +29,8 @@ bitflags = "1.0" bytes = "1.0" futures-util = { version = "0.3", default-features = false, features = ["alloc"] } http = "0.2" -http-body = "0.4.3" -hyper = { version = "0.14", features = ["server", "tcp", "stream"] } +http-body = "0.4.4" +hyper = { version = "0.14.14", features = ["server", "tcp", "stream"] } matchit = "0.4.4" percent-encoding = "2.1" pin-project-lite = "0.2.7" diff --git a/src/body.rs b/src/body.rs index 8e9c6a9420c..cc11a15c66c 100644 --- a/src/body.rs +++ b/src/body.rs @@ -20,15 +20,15 @@ pub use bytes::Bytes; /// /// This is used in axum as the response body type for applications. Its /// necessary to unify multiple response bodies types into one. -pub type BoxBody = http_body::combinators::BoxBody; +pub type BoxBody = http_body::combinators::UnsyncBoxBody; /// Convert a [`http_body::Body`] into a [`BoxBody`]. pub fn box_body(body: B) -> BoxBody where - B: http_body::Body + Send + Sync + 'static, + B: http_body::Body + Send + 'static, B::Error: Into, { - body.map_err(Error::new).boxed() + body.map_err(Error::new).boxed_unsync() } pub(crate) fn empty() -> BoxBody { diff --git a/src/error_handling/mod.rs b/src/error_handling/mod.rs index 176ba608841..54456dad40f 100644 --- a/src/error_handling/mod.rs +++ b/src/error_handling/mod.rs @@ -114,8 +114,8 @@ where S: Service, Response = Response> + Clone, F: FnOnce(S::Error) -> Res + Clone, Res: IntoResponse, - ResBody: http_body::Body + Send + Sync + 'static, - ResBody::Error: Into + Send + Sync + 'static, + ResBody: http_body::Body + Send + 'static, + ResBody::Error: Into, { type Response = Response; type Error = Infallible; @@ -181,8 +181,8 @@ pub mod future { Fut: Future, E>>, F: FnOnce(E) -> Res, Res: IntoResponse, - B: http_body::Body + Send + Sync + 'static, - B::Error: Into + Send + Sync + 'static, + B: http_body::Body + Send + 'static, + B::Error: Into, { type Output = Result, Infallible>; diff --git a/src/extract/extractor_middleware.rs b/src/extract/extractor_middleware.rs index 7ed8cb762b4..5a68f802154 100644 --- a/src/extract/extractor_middleware.rs +++ b/src/extract/extractor_middleware.rs @@ -154,7 +154,7 @@ where E: FromRequest + 'static, ReqBody: Default + Send + 'static, S: Service, Response = Response> + Clone, - ResBody: http_body::Body + Send + Sync + 'static, + ResBody: http_body::Body + Send + 'static, ResBody::Error: Into, { type Response = Response; @@ -213,7 +213,7 @@ where E: FromRequest, S: Service, Response = Response>, ReqBody: Default, - ResBody: http_body::Body + Send + Sync + 'static, + ResBody: http_body::Body + Send + 'static, ResBody::Error: Into, { type Output = Result, S::Error>; diff --git a/src/handler/mod.rs b/src/handler/mod.rs index 64cf4250ae0..50ac80320ed 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -281,8 +281,8 @@ where S::Future: Send, T: 'static, ReqBody: Send + 'static, - ResBody: http_body::Body + Send + Sync + 'static, - ResBody::Error: Into + Send + Sync + 'static, + ResBody: http_body::Body + Send + 'static, + ResBody::Error: Into, { type Sealed = sealed::Hidden; diff --git a/src/response/headers.rs b/src/response/headers.rs index 2b086e1f300..c4c9bcb6abd 100644 --- a/src/response/headers.rs +++ b/src/response/headers.rs @@ -115,7 +115,7 @@ where impl IntoResponse for (Headers, T) where T: IntoResponse, - T::Body: Body + Send + Sync + 'static, + T::Body: Body + Send + 'static, ::Error: Into, H: IntoIterator, K: TryInto, @@ -141,7 +141,7 @@ where impl IntoResponse for (StatusCode, Headers, T) where T: IntoResponse, - T::Body: Body + Send + Sync + 'static, + T::Body: Body + Send + 'static, ::Error: Into, H: IntoIterator, K: TryInto, diff --git a/src/response/mod.rs b/src/response/mod.rs index ec2f8a63d9d..41efb8a556a 100644 --- a/src/response/mod.rs +++ b/src/response/mod.rs @@ -163,7 +163,7 @@ pub trait IntoResponse { /// [`axum::body::Empty`]: crate::body::Empty /// [`axum::body::Full`]: crate::body::Full /// [`axum::body::BoxBody`]: crate::body::BoxBody - type Body: http_body::Body + Send + Sync + 'static; + type Body: http_body::Body + Send + 'static; /// The error type `Self::Body` might generate. /// @@ -217,7 +217,7 @@ where impl IntoResponse for Response where - B: http_body::Body + Send + Sync + 'static, + B: http_body::Body + Send + 'static, B::Error: Into, { type Body = B; @@ -259,8 +259,8 @@ where impl IntoResponse for MapData where - B: http_body::Body + Send + Sync + 'static, - F: FnMut(B::Data) -> Bytes + Send + Sync + 'static, + B: http_body::Body + Send + 'static, + F: FnMut(B::Data) -> Bytes + Send + 'static, B::Error: Into, { type Body = Self; @@ -273,8 +273,8 @@ where impl IntoResponse for MapErr where - B: http_body::Body + Send + Sync + 'static, - F: FnMut(B::Error) -> E + Send + Sync + 'static, + B: http_body::Body + Send + 'static, + F: FnMut(B::Error) -> E + Send + 'static, E: Into, { type Body = Self; diff --git a/src/routing/method_not_allowed.rs b/src/routing/method_not_allowed.rs index 5dbc400f2d7..a1d47665039 100644 --- a/src/routing/method_not_allowed.rs +++ b/src/routing/method_not_allowed.rs @@ -41,7 +41,7 @@ impl fmt::Debug for MethodNotAllowed { impl Service> for MethodNotAllowed where - B: Send + Sync + 'static, + B: Send + 'static, { type Response = Response; type Error = E; diff --git a/src/routing/mod.rs b/src/routing/mod.rs index 361b849d2ab..89587fb52cb 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -77,7 +77,7 @@ impl Clone for Router { impl Default for Router where - B: Send + Sync + 'static, + B: Send + 'static, { fn default() -> Self { Self::new() @@ -99,7 +99,7 @@ const NEST_TAIL_PARAM_CAPTURE: &str = "/*axum_nest"; impl Router where - B: Send + Sync + 'static, + B: Send + 'static, { /// Create a new `Router`. /// @@ -240,7 +240,7 @@ where + Send + 'static, >>::Future: Send + 'static, - LayeredResBody: http_body::Body + Send + Sync + 'static, + LayeredResBody: http_body::Body + Send + 'static, LayeredResBody::Error: Into, { let layer = ServiceBuilder::new() @@ -361,7 +361,7 @@ where impl Service> for Router where - B: Send + Sync + 'static, + B: Send + 'static, { type Response = Response; type Error = Infallible; diff --git a/src/routing/not_found.rs b/src/routing/not_found.rs index 8f7b689d80f..ef02dec2ffe 100644 --- a/src/routing/not_found.rs +++ b/src/routing/not_found.rs @@ -16,7 +16,7 @@ pub(crate) struct NotFound; impl Service> for NotFound where - B: Send + Sync + 'static, + B: Send + 'static, { type Response = Response; type Error = Infallible; diff --git a/src/routing/service_method_routing.rs b/src/routing/service_method_routing.rs index 49747fa765f..2dcb09d5462 100644 --- a/src/routing/service_method_routing.rs +++ b/src/routing/service_method_routing.rs @@ -464,7 +464,7 @@ impl MethodRouter { impl Service> for MethodRouter where S: Service, Response = Response> + Clone, - ResBody: http_body::Body + Send + Sync + 'static, + ResBody: http_body::Body + Send + 'static, ResBody::Error: Into, F: Service, Response = Response, Error = S::Error> + Clone, { @@ -514,7 +514,7 @@ pin_project! { impl Future for MethodRouterFuture where S: Service, Response = Response> + Clone, - ResBody: http_body::Body + Send + Sync + 'static, + ResBody: http_body::Body + Send + 'static, ResBody::Error: Into, F: Service, Response = Response, Error = S::Error>, {