diff --git a/tonic/src/transport/server/mod.rs b/tonic/src/transport/server/mod.rs index 4ff5aa04b..265112736 100644 --- a/tonic/src/transport/server/mod.rs +++ b/tonic/src/transport/server/mod.rs @@ -19,7 +19,7 @@ use super::service::{Or, Routes, ServerIo, ServiceBuilderExt}; use crate::{body::BoxBody, request::ConnectionInfo}; use futures_core::Stream; use futures_util::{ - future::{self, MapErr}, + future::{self, Either, MapErr}, TryFutureExt, }; use http::{HeaderMap, Request, Response}; @@ -71,6 +71,51 @@ pub struct Router { routes: Routes>, } +#[derive(Debug)] +/// a service made from a router +pub struct RouterService { + router: Router, +} + +/// create a tower service out of a router +pub fn service(router: Router) -> RouterService +where + A: Service, Response = Response> + Clone + Send + 'static, + A::Future: Send + 'static, + A::Error: Into + Send, + B: Service, Response = Response> + Clone + Send + 'static, + B::Future: Send + 'static, + B::Error: Into + Send, +{ + RouterService { router } +} + +impl Service> for RouterService +where + A: Service, Response = Response> + Clone + Send + 'static, + A::Future: Send + 'static, + A::Error: Into + Send, + B: Service, Response = Response> + Clone + Send + 'static, + B::Future: Send + 'static, + B::Error: Into + Send, +{ + type Response = Response; + type Future = Either< + MapErr crate::Error>, + MapErr crate::Error>, + >; + type Error = crate::Error; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + #[inline] + fn call(&mut self, req: Request) -> Self::Future { + self.router.routes.call(req) + } +} + /// A trait to provide a static reference to the service's /// name. This is used for routing service's within the router. pub trait NamedService {