From 66eee6152a690e5b6afa693600954c3e1f2d9b5f Mon Sep 17 00:00:00 2001 From: Fangdun Tsai Date: Sun, 17 Dec 2023 03:33:16 +0800 Subject: [PATCH] feat(core): improve handlers and add ServiceHandler (#117) --- viz-core/src/handler.rs | 36 ++++++++++++----- viz-core/src/handler/after.rs | 3 +- viz-core/src/handler/and_then.rs | 3 +- viz-core/src/handler/around.rs | 3 +- viz-core/src/handler/before.rs | 3 +- viz-core/src/handler/catch_error.rs | 3 +- viz-core/src/handler/catch_unwind.rs | 5 ++- viz-core/src/handler/either.rs | 7 ++-- viz-core/src/handler/fn_ext_hanlder.rs | 4 +- viz-core/src/handler/into_handler.rs | 4 +- viz-core/src/handler/map.rs | 3 +- viz-core/src/handler/map_err.rs | 3 +- viz-core/src/handler/map_into_response.rs | 4 +- viz-core/src/handler/or_else.rs | 3 +- viz-core/src/handler/service.rs | 48 +++++++++++++++++++++++ 15 files changed, 104 insertions(+), 28 deletions(-) create mode 100644 viz-core/src/handler/service.rs diff --git a/viz-core/src/handler.rs b/viz-core/src/handler.rs index efe5337a..a312d4d9 100644 --- a/viz-core/src/handler.rs +++ b/viz-core/src/handler.rs @@ -50,6 +50,9 @@ pub use or_else::OrElse; mod transform; pub use transform::Transform; +mod service; +pub use service::ServiceHandler; + /// A simplified asynchronous interface for handling input and output. /// /// Composable request handlers. @@ -83,14 +86,6 @@ where /// [`FutureExt`]: https://docs.rs/futures/latest/futures/future/trait.FutureExt.html /// [`StreamExt`]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html pub trait HandlerExt: Handler { - /// Converts this Handler into a [`BoxHandler`]. - fn boxed(self) -> BoxHandler - where - Self: Sized, - { - Box::new(self) - } - /// Maps the input before the handler calls. fn before(self, f: F) -> Before where @@ -115,6 +110,21 @@ pub trait HandlerExt: Handler { Around::new(self, f) } + /// Wraps this handler in an Either handler, making it the left-hand variant of that Either. + /// + /// Returns the left-hand variant if `enable` is true, otherwise returns the right-hand + /// variant. + fn either(self, r: R, enable: bool) -> Either + where + Self: Sized, + { + if enable { + Either::Left(self) + } else { + Either::Right(r) + } + } + /// Maps the `Ok` value of the output if after the handler called. fn map(self, f: F) -> Map where @@ -173,7 +183,15 @@ pub trait HandlerExt: Handler { CatchUnwind::new(self, f) } - /// Returns a new [Handler] that wrapping the `Self` and a type implementing [`Transform`]. + /// Converts this Handler into a [`BoxHandler`]. + fn boxed(self) -> BoxHandler + where + Self: Sized, + { + Box::new(self) + } + + /// Returns a new [`Handler`] that wrapping the `Self` and a type implementing [`Transform`]. fn with(self, t: T) -> T::Output where T: Transform, diff --git a/viz-core/src/handler/after.rs b/viz-core/src/handler/after.rs index b478a56e..0ff25ba1 100644 --- a/viz-core/src/handler/after.rs +++ b/viz-core/src/handler/after.rs @@ -8,8 +8,9 @@ pub struct After { } impl After { + /// Creates an [`After`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/and_then.rs b/viz-core/src/handler/and_then.rs index 579497d5..aa32dc24 100644 --- a/viz-core/src/handler/and_then.rs +++ b/viz-core/src/handler/and_then.rs @@ -8,8 +8,9 @@ pub struct AndThen { } impl AndThen { + /// Creates an [`AndThen`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/around.rs b/viz-core/src/handler/around.rs index 455ccb17..342efafe 100644 --- a/viz-core/src/handler/around.rs +++ b/viz-core/src/handler/around.rs @@ -11,8 +11,9 @@ pub struct Around { } impl Around { + /// Creates an [`Around`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/before.rs b/viz-core/src/handler/before.rs index 11d495a7..309fa7ec 100644 --- a/viz-core/src/handler/before.rs +++ b/viz-core/src/handler/before.rs @@ -8,8 +8,9 @@ pub struct Before { } impl Before { + /// Creates a [`Before`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/catch_error.rs b/viz-core/src/handler/catch_error.rs index 0ad10a6c..692f31ce 100644 --- a/viz-core/src/handler/catch_error.rs +++ b/viz-core/src/handler/catch_error.rs @@ -25,8 +25,9 @@ where } impl CatchError { + /// Creates a [`CatchError`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f, diff --git a/viz-core/src/handler/catch_unwind.rs b/viz-core/src/handler/catch_unwind.rs index 7dcc9cb8..81fe847d 100644 --- a/viz-core/src/handler/catch_unwind.rs +++ b/viz-core/src/handler/catch_unwind.rs @@ -12,8 +12,9 @@ pub struct CatchUnwind { } impl CatchUnwind { + /// Creates an [`CatchUnwind`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } @@ -22,8 +23,8 @@ impl CatchUnwind { impl Handler for CatchUnwind where I: Send + 'static, - O: IntoResponse + Send, H: Handler> + Clone, + O: IntoResponse + Send, F: Handler, Output = R> + Clone, R: IntoResponse, { diff --git a/viz-core/src/handler/either.rs b/viz-core/src/handler/either.rs index 0fecc3e9..5a3ad828 100644 --- a/viz-core/src/handler/either.rs +++ b/viz-core/src/handler/either.rs @@ -19,9 +19,10 @@ where type Output = O; async fn call(&self, i: I) -> Self::Output { - match self { - Self::Left(l) => l.call(i).await, - Self::Right(r) => r.call(i).await, + match &self { + Self::Left(l) => l.call(i), + Self::Right(r) => r.call(i), } + .await } } diff --git a/viz-core/src/handler/fn_ext_hanlder.rs b/viz-core/src/handler/fn_ext_hanlder.rs index 99fd3026..665f9bb9 100644 --- a/viz-core/src/handler/fn_ext_hanlder.rs +++ b/viz-core/src/handler/fn_ext_hanlder.rs @@ -16,8 +16,8 @@ where } impl FnExtHandler { - /// Create a new `Handler` for the extractors. - pub(super) fn new(h: H) -> Self { + /// Creates a new `Handler` for the extractors. + pub fn new(h: H) -> Self { Self(h, PhantomData) } } diff --git a/viz-core/src/handler/into_handler.rs b/viz-core/src/handler/into_handler.rs index c62bd8b0..5ca17b8d 100644 --- a/viz-core/src/handler/into_handler.rs +++ b/viz-core/src/handler/into_handler.rs @@ -2,12 +2,12 @@ use crate::{FromRequest, IntoResponse, Request, Result}; use super::{FnExt, FnExtHandler, Handler}; -/// Trait implemented by types that can be converted to a [`Handler`]. +/// The trait implemented by types that can be converted to a [`Handler`]. pub trait IntoHandler { /// The target handler. type Handler: Handler; - /// Convert self to a [Handler]. + /// Converts self to a [`Handler`]. #[must_use] fn into_handler(self) -> Self::Handler; } diff --git a/viz-core/src/handler/map.rs b/viz-core/src/handler/map.rs index 9f7c9dd6..2a5a0503 100644 --- a/viz-core/src/handler/map.rs +++ b/viz-core/src/handler/map.rs @@ -8,8 +8,9 @@ pub struct Map { } impl Map { + /// Creates a [`Map`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/map_err.rs b/viz-core/src/handler/map_err.rs index 22fe4a19..54bdcdd4 100644 --- a/viz-core/src/handler/map_err.rs +++ b/viz-core/src/handler/map_err.rs @@ -8,8 +8,9 @@ pub struct MapErr { } impl MapErr { + /// Creates a [`MapErr`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/map_into_response.rs b/viz-core/src/handler/map_into_response.rs index c923f3d5..4718990d 100644 --- a/viz-core/src/handler/map_into_response.rs +++ b/viz-core/src/handler/map_into_response.rs @@ -5,9 +5,9 @@ use crate::{async_trait, Handler, IntoResponse, Response, Result}; pub struct MapInToResponse(pub(crate) H); impl MapInToResponse { - /// Creates a new `Responder`. + /// Creates a [`MapInToResponse`] handler. #[inline] - pub(super) fn new(h: H) -> Self { + pub fn new(h: H) -> Self { Self(h) } } diff --git a/viz-core/src/handler/or_else.rs b/viz-core/src/handler/or_else.rs index 752128b6..5b8c71b4 100644 --- a/viz-core/src/handler/or_else.rs +++ b/viz-core/src/handler/or_else.rs @@ -8,8 +8,9 @@ pub struct OrElse { } impl OrElse { + /// Creates an [`OrElse`] handler. #[inline] - pub(super) fn new(h: H, f: F) -> Self { + pub fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/service.rs b/viz-core/src/handler/service.rs new file mode 100644 index 00000000..af53e054 --- /dev/null +++ b/viz-core/src/handler/service.rs @@ -0,0 +1,48 @@ +use http_body_util::BodyExt; +use hyper::service::Service; + +use crate::{async_trait, Body, Bytes, Error, Handler, Request, Response, Result}; + +/// Converts a hyper [`Service`] to a viz [`Handler`]. +#[derive(Debug, Clone)] +pub struct ServiceHandler { + s: S, +} + +impl ServiceHandler { + /// Creates a new [`ServiceHandler`]. + pub fn new(s: S) -> Self { + Self { s } + } +} + +#[async_trait] +impl Handler> for ServiceHandler +where + I: Body + Send + Unpin + 'static, + // O: Body + Send + 'static, + O: Body + Send + Sync + 'static, + O::Data: Into, + O::Error: Into, + S: Service, Response = Response> + Send + Sync + Clone + 'static, + S::Future: Send, + S::Error: Into, +{ + type Output = Result; + + async fn call(&self, req: Request) -> Self::Output { + self.s + .call(req) + .await + .map(|resp| { + resp.map(|body| { + body.map_frame(|f| f.map_data(Into::into)) + .map_err(Into::into) + // .boxed_unsync() + .boxed() + }) + .map(Into::into) + }) + .map_err(Into::into) + } +}