/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 | | } |