apache_dubbo/triple/transport/
router.rs1use std::fmt;
19use std::pin::Pin;
20use std::task::Context;
21use std::task::Poll;
22
23use axum::Router;
24use futures_core::Future;
25use hyper::{Body, Request, Response};
26use pin_project::pin_project;
27use tower::ServiceExt;
28use tower_service::Service;
29
30use crate::BoxBody;
31
32#[derive(Debug, Clone, Default)]
33pub struct DubboRouter {
34 pub router: Router,
35}
36
37impl DubboRouter {
38 pub fn new() -> DubboRouter {
39 Self {
40 router: Router::new(),
41 }
42 }
43}
44
45impl DubboRouter {
46 pub fn add_service<S>(mut self, name: String, service: S) -> Self
47 where
48 S: Service<Request<Body>, Response = Response<BoxBody>, Error = std::convert::Infallible>
49 + Clone
50 + Send
51 + 'static,
52 S::Future: Send + 'static,
53 {
54 let svc = service.map_response(|res| res.map(axum::body::boxed));
55 self.router = self.router.route(&format!("/{}/*dubbo", name), svc);
57
58 self
59 }
60}
61
62impl Service<Request<Body>> for DubboRouter {
63 type Response = Response<BoxBody>;
64 type Error = crate::Error;
65 type Future = RoutesFuture;
66
67 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
68 Poll::Ready(Ok(()))
69 }
70
71 fn call(&mut self, req: Request<Body>) -> Self::Future {
72 RoutesFuture(self.router.call(req))
73 }
74}
75
76#[pin_project]
77pub struct RoutesFuture(#[pin] axum::routing::future::RouteFuture<Body, std::convert::Infallible>);
78
79impl fmt::Debug for RoutesFuture {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 f.debug_tuple("RoutesFuture").finish()
82 }
83}
84
85impl Future for RoutesFuture {
86 type Output = Result<Response<BoxBody>, crate::Error>;
87
88 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
89 match futures_util::ready!(self.project().0.poll(cx)) {
90 Ok(res) => Ok(res.map(crate::boxed)).into(),
91 Err(err) => match err {},
92 }
93 }
94}