1use std::{convert::Infallible, future::Future, marker::PhantomData};
12
13use http::status::StatusCode;
14use motore::{ServiceExt, layer::Layer, service::Service};
15
16use super::{IntoResponse, handler::Handler};
17use crate::{body::Body, context::ServerContext, request::Request, response::Response};
18
19pub mod method_router;
20pub mod router;
21mod utils;
22
23pub use self::{method_router::*, router::Router};
24
25pub struct Route<B = Body, E = Infallible> {
27 inner: motore::service::BoxService<ServerContext, Request<B>, Response, E>,
28}
29
30impl<B, E> Route<B, E> {
31 pub fn new<S>(inner: S) -> Self
33 where
34 S: Service<ServerContext, Request<B>, Response = Response, Error = E>
35 + Send
36 + Sync
37 + 'static,
38 B: 'static,
39 {
40 Self {
41 inner: motore::service::BoxService::new(inner),
42 }
43 }
44}
45
46impl<B, E> Service<ServerContext, Request<B>> for Route<B, E> {
47 type Response = Response;
48 type Error = E;
49
50 fn call(
51 &self,
52 cx: &mut ServerContext,
53 req: Request<B>,
54 ) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
55 self.inner.call(cx, req)
56 }
57}
58
59enum Fallback<B = Body, E = Infallible> {
60 Route(Route<B, E>),
61}
62
63impl<B, E> Service<ServerContext, Request<B>> for Fallback<B, E>
64where
65 B: Send,
66{
67 type Response = Response;
68 type Error = E;
69
70 async fn call(
71 &self,
72 cx: &mut ServerContext,
73 req: Request<B>,
74 ) -> Result<Self::Response, Self::Error> {
75 match self {
76 Self::Route(route) => route.call(cx, req).await,
77 }
78 }
79}
80
81impl<B, E> Fallback<B, E>
82where
83 B: Send + 'static,
84 E: 'static,
85{
86 fn from_status_code(status: StatusCode) -> Self {
87 Self::from_service(RouteForStatusCode::new(status))
88 }
89
90 fn from_handler<H, T>(handler: H) -> Self
91 where
92 H: Handler<T, B, E> + Clone + Send + Sync + 'static,
93 T: 'static,
94 {
95 Self::from_service(handler.into_service())
96 }
97
98 fn from_service<S>(service: S) -> Self
99 where
100 S: Service<ServerContext, Request<B>, Error = E> + Send + Sync + 'static,
101 S::Response: IntoResponse,
102 {
103 Self::Route(Route::new(
104 service.map_response(IntoResponse::into_response),
105 ))
106 }
107
108 fn map<F, B2, E2>(self, f: F) -> Fallback<B2, E2>
109 where
110 F: FnOnce(Route<B, E>) -> Route<B2, E2> + Clone + 'static,
111 {
112 match self {
113 Self::Route(route) => Fallback::Route(f(route)),
114 }
115 }
116
117 fn layer<L, B2, E2>(self, l: L) -> Fallback<B2, E2>
118 where
119 L: Layer<Route<B, E>> + Clone + Send + Sync + 'static,
120 L::Service: Service<ServerContext, Request<B2>, Error = E2> + Send + Sync + 'static,
121 <L::Service as Service<ServerContext, Request<B2>>>::Response: IntoResponse,
122 B2: 'static,
123 {
124 self.map(move |route: Route<B, E>| {
125 Route::new(
126 l.clone()
127 .layer(route)
128 .map_response(IntoResponse::into_response),
129 )
130 })
131 }
132}
133
134struct RouteForStatusCode<B, E> {
135 status: StatusCode,
136 _marker: PhantomData<fn(B, E)>,
137}
138
139impl<B, E> Clone for RouteForStatusCode<B, E> {
140 fn clone(&self) -> Self {
141 Self {
142 status: self.status,
143 _marker: self._marker,
144 }
145 }
146}
147
148impl<B, E> RouteForStatusCode<B, E> {
149 fn new(status: StatusCode) -> Self {
150 Self {
151 status,
152 _marker: PhantomData,
153 }
154 }
155}
156
157impl<B, E> Service<ServerContext, Request<B>> for RouteForStatusCode<B, E>
158where
159 B: Send,
160{
161 type Response = Response;
162 type Error = E;
163
164 async fn call(
165 &self,
166 _: &mut ServerContext,
167 _: Request<B>,
168 ) -> Result<Self::Response, Self::Error> {
169 Ok(self.status.into_response())
170 }
171}