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 {