Coverage Report

Created: 2026-03-31 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tonic-0.14.5/src/service/router.rs
Line
Count
Source
1
use crate::{body::Body, server::NamedService, Status};
2
use http::{Request, Response};
3
use std::{
4
    convert::Infallible,
5
    fmt,
6
    future::Future,
7
    pin::Pin,
8
    task::{Context, Poll},
9
};
10
use tower::{Service, ServiceExt};
11
12
/// A [`Service`] router.
13
#[derive(Debug, Clone)]
14
pub struct Routes {
15
    router: axum::Router,
16
}
17
18
#[derive(Debug, Default, Clone)]
19
/// Allows adding new services to routes by passing a mutable reference to this builder.
20
pub struct RoutesBuilder {
21
    routes: Option<Routes>,
22
}
23
24
impl RoutesBuilder {
25
    /// Add a new service.
26
0
    pub fn add_service<S>(&mut self, svc: S) -> &mut Self
27
0
    where
28
0
        S: Service<Request<Body>, Error = Infallible>
29
0
            + NamedService
30
0
            + Clone
31
0
            + Send
32
0
            + Sync
33
0
            + 'static,
34
0
        S::Response: axum::response::IntoResponse,
35
0
        S::Future: Send + 'static,
36
    {
37
0
        let routes = self.routes.take().unwrap_or_default();
38
0
        self.routes.replace(routes.add_service(svc));
39
0
        self
40
0
    }
41
42
    /// Returns the routes with added services or empty [`Routes`] if no service was added
43
0
    pub fn routes(self) -> Routes {
44
0
        self.routes.unwrap_or_default()
45
0
    }
46
}
47
48
impl Default for Routes {
49
0
    fn default() -> Self {
50
0
        Self {
51
0
            router: axum::Router::new().fallback(unimplemented),
52
0
        }
53
0
    }
54
}
55
56
impl Routes {
57
    /// Create a new routes with `svc` already added to it.
58
0
    pub fn new<S>(svc: S) -> Self
59
0
    where
60
0
        S: Service<Request<Body>, Error = Infallible>
61
0
            + NamedService
62
0
            + Clone
63
0
            + Send
64
0
            + Sync
65
0
            + 'static,
66
0
        S::Response: axum::response::IntoResponse,
67
0
        S::Future: Send + 'static,
68
    {
69
0
        Self::default().add_service(svc)
70
0
    }
71
72
    /// Create a new empty builder.
73
0
    pub fn builder() -> RoutesBuilder {
74
0
        RoutesBuilder::default()
75
0
    }
76
77
    /// Add a new service.
78
0
    pub fn add_service<S>(mut self, svc: S) -> Self
79
0
    where
80
0
        S: Service<Request<Body>, Error = Infallible>
81
0
            + NamedService
82
0
            + Clone
83
0
            + Send
84
0
            + Sync
85
0
            + 'static,
86
0
        S::Response: axum::response::IntoResponse,
87
0
        S::Future: Send + 'static,
88
    {
89
0
        self.router = self.router.route_service(
90
0
            &format!("/{}/{{*rest}}", S::NAME),
91
0
            svc.map_request(|req: Request<axum::body::Body>| req.map(Body::new)),
92
        );
93
0
        self
94
0
    }
95
96
    /// This makes axum perform update some internals of the router that improves perf.
97
    ///
98
    /// See <https://docs.rs/axum/latest/axum/routing/struct.Router.html#a-note-about-performance>
99
0
    pub fn prepare(self) -> Self {
100
0
        Self {
101
0
            router: self.router.with_state(()),
102
0
        }
103
0
    }
104
105
    /// Convert this `Routes` into an [`axum::Router`].
106
0
    pub fn into_axum_router(self) -> axum::Router {
107
0
        self.router
108
0
    }
109
110
    /// Get a mutable reference to the [`axum::Router`].
111
0
    pub fn axum_router_mut(&mut self) -> &mut axum::Router {
112
0
        &mut self.router
113
0
    }
114
}
115
116
impl From<Routes> for RoutesBuilder {
117
0
    fn from(routes: Routes) -> Self {
118
0
        Self {
119
0
            routes: Some(routes),
120
0
        }
121
0
    }
122
}
123
124
impl From<axum::Router> for RoutesBuilder {
125
0
    fn from(router: axum::Router) -> Self {
126
0
        Self {
127
0
            routes: Some(router.into()),
128
0
        }
129
0
    }
130
}
131
132
impl From<axum::Router> for Routes {
133
0
    fn from(router: axum::Router) -> Self {
134
0
        Self { router }
135
0
    }
136
}
137
138
0
async fn unimplemented() -> Response<Body> {
139
0
    let (parts, ()) = Status::unimplemented("").into_http::<()>().into_parts();
140
0
    Response::from_parts(parts, Body::empty())
141
0
}
142
143
impl<B> Service<Request<B>> for Routes
144
where
145
    B: http_body::Body<Data = bytes::Bytes> + Send + 'static,
146
    B::Error: Into<crate::BoxError>,
147
{
148
    type Response = Response<Body>;
149
    type Error = Infallible;
150
    type Future = RoutesFuture;
151
152
    #[inline]
153
0
    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
154
0
        Service::<Request<B>>::poll_ready(&mut self.router, cx)
155
0
    }
156
157
0
    fn call(&mut self, req: Request<B>) -> Self::Future {
158
0
        RoutesFuture(self.router.call(req))
159
0
    }
160
}
161
162
pub struct RoutesFuture(axum::routing::future::RouteFuture<Infallible>);
163
164
impl fmt::Debug for RoutesFuture {
165
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166
0
        f.debug_tuple("RoutesFuture").finish()
167
0
    }
168
}
169
170
impl Future for RoutesFuture {
171
    type Output = Result<Response<Body>, Infallible>;
172
173
0
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
174
0
        Pin::new(&mut self.as_mut().0)
175
0
            .poll(cx)
176
0
            .map_ok(|res| res.map(Body::new))
177
0
    }
178
}