From a09fe486937bb93f2eaebccc1d66fae31718f7de Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Sun, 3 Jul 2022 00:58:33 +0200 Subject: [PATCH] checkpoint --- axum/src/handler/into_service.rs | 33 +++++++++++++++++----------- axum/src/handler/mod.rs | 37 +++++++++++++++++--------------- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/axum/src/handler/into_service.rs b/axum/src/handler/into_service.rs index 34f36b2d..180ebdb1 100644 --- a/axum/src/handler/into_service.rs +++ b/axum/src/handler/into_service.rs @@ -12,51 +12,59 @@ use tower_service::Service; /// An adapter that makes a [`Handler`] into a [`Service`]. /// /// Created with [`Handler::into_service`]. -pub struct IntoService { +pub struct IntoService { handler: H, + state: S, _marker: PhantomData (T, B)>, } #[test] fn traits() { use crate::test_helpers::*; - assert_send::>(); - assert_sync::>(); + assert_send::>(); + assert_sync::>(); } -impl IntoService { - pub(super) fn new(handler: H) -> Self { +impl IntoService { + pub(super) fn new(handler: H, state: S) -> Self { Self { handler, + state, _marker: PhantomData, } } } -impl fmt::Debug for IntoService { +impl fmt::Debug for IntoService +where + S: fmt::Debug, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoService") - .field(&format_args!("...")) + f.debug_struct("IntoService") + .field("state", &self.state) .finish() } } -impl Clone for IntoService +impl Clone for IntoService where H: Clone, + S: Clone, { fn clone(&self) -> Self { Self { handler: self.handler.clone(), + state: self.state.clone(), _marker: PhantomData, } } } -impl Service> for IntoService +impl Service> for IntoService where - H: Handler + Clone + Send + 'static, + H: Handler + Clone + Send + 'static, B: Send + 'static, + S: Clone, { type Response = Response; type Error = Infallible; @@ -74,7 +82,8 @@ where use futures_util::future::FutureExt; let handler = self.handler.clone(); - let future = Handler::call(handler, req); + let state = self.state.clone(); + let future = Handler::call(handler, state, req); let future = future.map(Ok as _); super::future::IntoServiceFuture::new(future) diff --git a/axum/src/handler/mod.rs b/axum/src/handler/mod.rs index 69482fec..dbf3d5ba 100644 --- a/axum/src/handler/mod.rs +++ b/axum/src/handler/mod.rs @@ -61,12 +61,12 @@ pub use self::into_service::IntoService; /// See the [module docs](crate::handler) for more details. /// #[doc = include_str!("../docs/debugging_handler_type_errors.md")] -pub trait Handler: Clone + Send + Sized + 'static { +pub trait Handler: Clone + Send + Sized + 'static { /// The type of future calling this handler returns. type Future: Future + Send + 'static; /// Call the handler with the given request. - fn call(self, req: Request) -> Self::Future; + fn call(self, state: S, req: Request) -> Self::Future; /// Apply a [`tower::Layer`] to the handler. /// @@ -106,9 +106,11 @@ pub trait Handler: Clone + Send + Sized + 'static { /// ``` fn layer(self, layer: L) -> Layered where - L: Layer>, + L: Layer>, { - Layered::new(layer.layer(self.into_service())) + // TODO(david): write this, somehow + todo!() + // Layered::new(layer.layer(self.into_service())) } /// Convert the handler into a [`Service`]. @@ -143,8 +145,8 @@ pub trait Handler: Clone + Send + Sized + 'static { /// ``` /// /// [`Router::fallback`]: crate::routing::Router::fallback - fn into_service(self) -> IntoService { - IntoService::new(self) + fn into_service(self, state: S) -> IntoService { + IntoService::new(self, state) } /// Convert the handler into a [`MakeService`]. @@ -170,8 +172,8 @@ pub trait Handler: Clone + Send + Sized + 'static { /// ``` /// /// [`MakeService`]: tower::make::MakeService - fn into_make_service(self) -> IntoMakeService> { - IntoMakeService::new(self.into_service()) + fn into_make_service(self, state: S) -> IntoMakeService> { + IntoMakeService::new(self.into_service(state)) } /// Convert the handler into a [`MakeService`] which stores information @@ -204,12 +206,13 @@ pub trait Handler: Clone + Send + Sized + 'static { /// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info fn into_make_service_with_connect_info( self, - ) -> IntoMakeServiceWithConnectInfo, C> { - IntoMakeServiceWithConnectInfo::new(self.into_service()) + state: S, + ) -> IntoMakeServiceWithConnectInfo, C> { + IntoMakeServiceWithConnectInfo::new(self.into_service(state)) } } -impl Handler<(), B> for F +impl Handler for F where F: FnOnce() -> Fut + Clone + Send + 'static, Fut: Future + Send, @@ -218,7 +221,7 @@ where { type Future = Pin + Send>>; - fn call(self, _req: Request) -> Self::Future { + fn call(self, _state: S, _req: Request) -> Self::Future { Box::pin(async move { self().await.into_response() }) } } @@ -226,7 +229,7 @@ where macro_rules! impl_handler { ( $($ty:ident),* $(,)? ) => { #[allow(non_snake_case)] - impl Handler<($($ty,)*), B> for F + impl Handler for F where F: FnOnce($($ty,)*) -> Fut + Clone + Send + 'static, Fut: Future + Send, @@ -236,7 +239,7 @@ macro_rules! impl_handler { { type Future = Pin + Send>>; - fn call(self, req: Request) -> Self::Future { + fn call(self, state: S, req: Request) -> Self::Future { Box::pin(async move { let mut req = RequestParts::new(req); @@ -284,7 +287,7 @@ where } } -impl Handler for Layered +impl Handler for Layered where S: Service, Response = Response> + Clone + Send + 'static, S::Error: IntoResponse, @@ -296,7 +299,7 @@ where { type Future = future::LayeredFuture; - fn call(self, req: Request) -> Self::Future { + fn call(self, state: St, req: Request) -> Self::Future { use futures_util::future::{FutureExt, Map}; let future: Map<_, fn(Result) -> _> = @@ -330,7 +333,7 @@ mod tests { format!("you said: {}", body) } - let client = TestClient::new(handle.into_service()); + let client = TestClient::new(handle.into_service(())); let res = client.post("/").body("hi there!").send().await; assert_eq!(res.status(), StatusCode::OK);