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