1use crate::error::{Error, IntoResponse, Result};
2use crate::extract::FromRequest;
3use crate::request::Request;
4use crate::response::Response;
5use std::future::Future;
6use std::pin::Pin;
7use std::sync::Arc;
8
9pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
10
11pub type Handler = Arc<dyn Fn(Request) -> BoxFuture<Response> + Send + Sync>;
13
14pub type FallibleHandler =
16 Arc<dyn Fn(Request) -> BoxFuture<Result<Response>> + Send + Sync>;
17
18pub(crate) type ErrorHandlerFn =
19 Arc<dyn Fn(Error) -> BoxFuture<Response> + Send + Sync>;
20
21pub trait IntoHandler<T> {
23 fn into_handler(self) -> FallibleHandler;
24}
25
26pub struct ResponseMarker;
27pub struct ResultMarker;
28
29impl<F, Fut, R> IntoHandler<(ResponseMarker,)> for F
30where
31 F: Fn(Request) -> Fut + Send + Sync + 'static,
32 Fut: Future<Output = R> + Send + 'static,
33 R: IntoResponse,
34{
35 fn into_handler(self) -> FallibleHandler {
36 Arc::new(move |req| {
37 let fut = self(req);
38 Box::pin(async move { Ok(fut.await.into_response()) })
39 })
40 }
41}
42
43impl<F, Fut, R> IntoHandler<(ResultMarker,)> for F
44where
45 F: Fn(Request) -> Fut + Send + Sync + 'static,
46 Fut: Future<Output = Result<R>> + Send + 'static,
47 R: IntoResponse,
48{
49 fn into_handler(self) -> FallibleHandler {
50 Arc::new(move |req| {
51 let fut = self(req);
52 Box::pin(async move { Ok(fut.await?.into_response()) })
53 })
54 }
55}
56
57pub trait ErrorResponse: IntoResponse {}
61
62pub struct FallibleResponseMarker;
64
65impl<F, Fut, R, E> IntoHandler<(FallibleResponseMarker, E)> for F
66where
67 F: Fn(Request) -> Fut + Send + Sync + 'static,
68 Fut: Future<Output = std::result::Result<R, E>> + Send + 'static,
69 R: IntoResponse,
70 E: ErrorResponse + 'static,
71{
72 fn into_handler(self) -> FallibleHandler {
73 Arc::new(move |req| {
74 let fut = self(req);
75 Box::pin(async move {
76 match fut.await {
77 Ok(r) => Ok(r.into_response()),
78 Err(e) => Ok(e.into_response()),
79 }
80 })
81 })
82 }
83}
84
85pub struct NoArgResponseMarker;
87
88impl<F, Fut, R> IntoHandler<(NoArgResponseMarker,)> for F
89where
90 F: Fn() -> Fut + Send + Sync + 'static,
91 Fut: Future<Output = R> + Send + 'static,
92 R: IntoResponse,
93{
94 fn into_handler(self) -> FallibleHandler {
95 Arc::new(move |_req| {
96 let fut = self();
97 Box::pin(async move { Ok(fut.await.into_response()) })
98 })
99 }
100}
101
102impl IntoHandler<()> for FallibleHandler {
103 fn into_handler(self) -> FallibleHandler {
104 self
105 }
106}
107
108macro_rules! impl_extract_handlers {
109 ($(($marker:ident, $($T:ident),+));+ $(;)?) => {
110 $(
111 pub struct $marker;
112 impl_extract_handlers!(@one $marker, $($T),+);
113 )+
114 };
115 (@one $marker:ident, $($T:ident),+) => {
116 impl<FnH, Fut, R, $($T),+> IntoHandler<($marker, $($T),+)> for FnH
117 where
118 FnH: Fn($($T),+) -> Fut + Send + Sync + 'static,
119 $($T: FromRequest + 'static,)+
120 Fut: Future<Output = R> + Send + 'static,
121 R: IntoResponse,
122 {
123 fn into_handler(self) -> FallibleHandler {
124 let handler = Arc::new(self);
125 Arc::new(move |mut req| {
126 let handler = Arc::clone(&handler);
127 Box::pin(async move {
128 $(
129 #[allow(non_snake_case)]
130 let $T = $T::from_request(&mut req).await?;
131 )+
132 Ok(handler($($T),+).await.into_response())
133 })
134 })
135 }
136 }
137
138 impl<FnH, Fut, R, $($T),+> IntoHandler<($marker, ResultMarker, $($T),+)> for FnH
139 where
140 FnH: Fn($($T),+) -> Fut + Send + Sync + 'static,
141 $($T: FromRequest + 'static,)+
142 Fut: Future<Output = Result<R>> + Send + 'static,
143 R: IntoResponse,
144 {
145 fn into_handler(self) -> FallibleHandler {
146 let handler = Arc::new(self);
147 Arc::new(move |mut req| {
148 let handler = Arc::clone(&handler);
149 Box::pin(async move {
150 $(
151 #[allow(non_snake_case)]
152 let $T = $T::from_request(&mut req).await?;
153 )+
154 Ok(handler($($T),+).await?.into_response())
155 })
156 })
157 }
158 }
159
160 impl<FnH, Fut, R, ErrE, $($T),+> IntoHandler<($marker, FallibleResponseMarker, ErrE, $($T),+)>
161 for FnH
162 where
163 FnH: Fn($($T),+) -> Fut + Send + Sync + 'static,
164 $($T: FromRequest + Send + 'static,)+
165 Fut: Future<Output = std::result::Result<R, ErrE>> + Send + 'static,
166 R: IntoResponse,
167 ErrE: ErrorResponse + Send + Sync + 'static,
168 {
169 fn into_handler(self) -> FallibleHandler {
170 let handler = Arc::new(self);
171 Arc::new(move |mut req| {
172 let handler = Arc::clone(&handler);
173 Box::pin(async move {
174 $(
175 #[allow(non_snake_case)]
176 let $T = $T::from_request(&mut req).await?;
177 )+
178 match handler($($T),+).await {
179 Ok(r) => Ok(r.into_response()),
180 Err(e) => Ok(e.into_response()),
181 }
182 })
183 })
184 }
185 }
186 };
187}
188
189impl_extract_handlers! {
190 (Extract1, T1);
191 (Extract2, T1, T2);
192 (Extract3, T1, T2, T3);
193 (Extract4, T1, T2, T3, T4);
194 (Extract5, T1, T2, T3, T4, T5);
195 (Extract6, T1, T2, T3, T4, T5, T6);
196 (Extract7, T1, T2, T3, T4, T5, T6, T7);
197 (Extract8, T1, T2, T3, T4, T5, T6, T7, T8);
198}
199
200pub fn wrap_errors(handler: FallibleHandler, eh: Option<ErrorHandlerFn>) -> Handler {
202 Arc::new(move |req| {
203 let handler = Arc::clone(&handler);
204 let eh = eh.clone();
205 let accept = req
206 .header("accept")
207 .unwrap_or("*/*")
208 .to_string();
209 Box::pin(async move {
210 crate::accept::with_accept(accept, async move {
211 match handler(req).await {
212 Ok(res) => res,
213 Err(Error::Response(res)) => *res,
215 Err(err) => match &eh {
216 Some(hook) => hook(err).await,
217 None => crate::accept::error_response_for_accept(None, err),
218 },
219 }
220 })
221 .await
222 })
223 })
224}