use super::Handler; #[cfg(feature = "tokio")] use crate::extract::connect_info::IntoMakeServiceWithConnectInfo; use crate::response::Response; use crate::routing::IntoMakeService; use http::Request; use std::{ convert::Infallible, fmt, marker::PhantomData, task::{Context, Poll}, }; use tower_service::Service; /// An adapter that makes a [`Handler`] into a [`Service`]. /// /// Created with [`Handler::with_state`] or [`HandlerWithoutStateExt::into_service`]. /// /// [`HandlerWithoutStateExt::into_service`]: super::HandlerWithoutStateExt::into_service pub struct HandlerService { handler: H, state: S, _marker: PhantomData (T, B)>, } impl HandlerService { /// Get a reference to the state. pub fn state(&self) -> &S { &self.state } /// Convert the handler into a [`MakeService`]. /// /// This allows you to serve a single handler if you don't need any routing: /// /// ```rust /// use axum::{ /// Server, /// handler::Handler, /// extract::State, /// http::{Uri, Method}, /// response::IntoResponse, /// }; /// use std::net::SocketAddr; /// /// #[derive(Clone)] /// struct AppState {} /// /// async fn handler(State(state): State) { /// // ... /// } /// /// let app = handler.with_state(AppState {}); /// /// # async { /// Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))) /// .serve(app.into_make_service()) /// .await?; /// # Ok::<_, hyper::Error>(()) /// # }; /// ``` /// /// [`MakeService`]: tower::make::MakeService pub fn into_make_service(self) -> IntoMakeService> { IntoMakeService::new(self) } /// Convert the handler into a [`MakeService`] which stores information /// about the incoming connection. /// /// See [`Router::into_make_service_with_connect_info`] for more details. /// /// ```rust /// use axum::{ /// Server, /// handler::Handler, /// response::IntoResponse, /// extract::{ConnectInfo, State}, /// }; /// use std::net::SocketAddr; /// /// #[derive(Clone)] /// struct AppState {}; /// /// async fn handler( /// ConnectInfo(addr): ConnectInfo, /// State(state): State, /// ) -> String { /// format!("Hello {}", addr) /// } /// /// let app = handler.with_state(AppState {}); /// /// # async { /// Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))) /// .serve(app.into_make_service_with_connect_info::()) /// .await?; /// # Ok::<_, hyper::Error>(()) /// # }; /// ``` /// /// [`MakeService`]: tower::make::MakeService /// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info #[cfg(feature = "tokio")] pub fn into_make_service_with_connect_info( self, ) -> IntoMakeServiceWithConnectInfo, C> { IntoMakeServiceWithConnectInfo::new(self) } } #[test] fn traits() { use crate::test_helpers::*; assert_send::>(); assert_sync::>(); } impl HandlerService { pub(super) fn new(handler: H, state: S) -> Self { Self { handler, state, _marker: PhantomData, } } } impl fmt::Debug for HandlerService { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntoService").finish_non_exhaustive() } } impl Clone for HandlerService where H: Clone, S: Clone, { fn clone(&self) -> Self { Self { handler: self.handler.clone(), state: self.state.clone(), _marker: PhantomData, } } } impl Service> for HandlerService where H: Handler + Clone + Send + 'static, B: Send + 'static, S: Clone + Send + Sync, { type Response = Response; type Error = Infallible; type Future = super::future::IntoServiceFuture; #[inline] fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { // `IntoService` can only be constructed from async functions which are always ready, or // from `Layered` which buffers in `::call` and is therefore // also always ready. Poll::Ready(Ok(())) } fn call(&mut self, req: Request) -> Self::Future { use futures_util::future::FutureExt; let handler = self.handler.clone(); let future = Handler::call(handler, req, self.state.clone()); let future = future.map(Ok as _); super::future::IntoServiceFuture::new(future) } }