1use hyper::{Request, Response};
9use std::future::Future;
10use std::pin::Pin;
11use std::sync::Arc;
12use std::task::{Context, Poll, Waker};
13
14use crate::http::response::{Body, IntoResponse};
15use crate::routing::extract::{FromRequest, FromRequestParts};
16
17pub enum ResponseFuture {
19 Ready(Option<Response<Body>>),
21 Boxed(Pin<Box<dyn Future<Output = Response<Body>> + Send + 'static>>),
23}
24
25impl std::fmt::Debug for ResponseFuture {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 match self {
28 Self::Ready(res) => f.debug_tuple("Ready").field(res).finish(),
29 Self::Boxed(_) => f.debug_tuple("Boxed").field(&"<future>").finish(),
30 }
31 }
32}
33
34impl Future for ResponseFuture {
35 type Output = Response<Body>;
36
37 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
38 match &mut *self {
39 Self::Ready(res) => res.take().map_or_else(
40 || unreachable!("ResponseFuture polled after completion"),
41 Poll::Ready,
42 ),
43 Self::Boxed(fut) => fut.as_mut().poll(cx),
44 }
45 }
46}
47
48fn noop_waker() -> Waker {
49 Waker::noop().clone()
50}
51
52pub type BoxedFuture = ResponseFuture;
54
55pub type BoxedHandler<S> =
57 Arc<dyn Fn(Request<Body>, Arc<S>) -> BoxedFuture + Send + Sync + 'static>;
58
59#[derive(Debug)]
61pub struct AsyncHandler<T>(std::marker::PhantomData<T>);
62
63#[derive(Debug)]
65pub struct SyncHandler<T>(std::marker::PhantomData<T>);
66
67pub trait Handler<T, S>: Clone + Send + Sync + 'static {
91 fn call(self, req: Request<Body>, state: Arc<S>) -> BoxedFuture;
93}
94
95impl<F, Fut, S, Res> Handler<AsyncHandler<()>, S> for F
99where
100 F: Fn() -> Fut + Clone + Send + Sync + 'static,
101 Fut: Future<Output = Res> + Send + 'static,
102 Res: IntoResponse + Send + 'static,
103 S: Send + Sync + 'static,
104{
105 fn call(self, _req: Request<Body>, _state: Arc<S>) -> BoxedFuture {
106 let mut boxed: Pin<Box<dyn Future<Output = Res> + Send>> = Box::pin(self());
114 let waker = noop_waker();
115 let mut cx = Context::from_waker(&waker);
116
117 match boxed.as_mut().poll(&mut cx) {
118 Poll::Ready(res) => ResponseFuture::Ready(Some(res.into_response())),
119 Poll::Pending => {
120 ResponseFuture::Boxed(Box::pin(async move { boxed.await.into_response() }))
121 }
122 }
123 }
124}
125
126impl<F, S, Res> Handler<SyncHandler<()>, S> for F
128where
129 F: Fn() -> Res + Clone + Send + Sync + 'static,
130 Res: IntoResponse + Send + 'static,
131 S: Send + Sync + 'static,
132{
133 fn call(self, _req: Request<Body>, _state: Arc<S>) -> BoxedFuture {
134 ResponseFuture::Ready(Some(self().into_response()))
135 }
136}
137
138macro_rules! impl_handler {
141 ( $($ty:ident),* ; $last:ident ) => {
142 impl<F, Fut, S, Res, $($ty,)* $last> Handler<AsyncHandler<( $($ty,)* $last, )>, S> for F
144 where
145 F: Fn($($ty,)* $last) -> Fut + Clone + Send + Sync + 'static,
146 Fut: Future<Output = Res> + Send + 'static,
147 Res: IntoResponse + Send + 'static,
148 $( $ty: FromRequestParts<S> + Send + 'static, )*
149 $last: FromRequest<S> + Send + 'static,
150 S: Send + Sync + 'static,
151 {
152 #[allow(non_snake_case, unused_mut)]
153 fn call(self, req: Request<Body>, state: Arc<S>) -> BoxedFuture {
154 let (mut parts, body) = req.into_parts();
155 $(
156 let $ty = match <$ty as FromRequestParts<S>>::from_request_parts(&mut parts, &*state) {
157 Ok(v) => v,
158 Err(r) => return ResponseFuture::Ready(Some(r.into_response())),
159 };
160 )*
161 ResponseFuture::Boxed(Box::pin(async move {
166 let req = Request::from_parts(parts, body);
167 let $last = match <$last as FromRequest<S>>::from_request(req, &*state).await {
168 Ok(v) => v,
169 Err(r) => return r.into_response(),
170 };
171 self($($ty,)* $last).await.into_response()
172 }))
173 }
174 }
175
176 impl<F, S, Res, $($ty,)* $last> Handler<SyncHandler<( $($ty,)* $last, )>, S> for F
178 where
179 F: Fn($($ty,)* $last) -> Res + Clone + Send + Sync + 'static,
180 Res: IntoResponse + Send + 'static,
181 $( $ty: FromRequestParts<S> + Send + 'static, )*
182 $last: FromRequest<S> + Send + 'static,
183 S: Send + Sync + 'static,
184 {
185 #[allow(non_snake_case, unused_mut)]
186 fn call(self, req: Request<Body>, state: Arc<S>) -> BoxedFuture {
187 let (mut parts, body) = req.into_parts();
188 $(
189 let $ty = match <$ty as FromRequestParts<S>>::from_request_parts(&mut parts, &*state) {
190 Ok(v) => v,
191 Err(r) => return ResponseFuture::Ready(Some(r.into_response())),
192 };
193 )*
194 ResponseFuture::Boxed(Box::pin(async move {
196 let req = Request::from_parts(parts, body);
197 let $last = match <$last as FromRequest<S>>::from_request(req, &*state).await {
198 Ok(v) => v,
199 Err(r) => return r.into_response(),
200 };
201 self($($ty,)* $last).into_response()
202 }))
203 }
204 }
205 };
206}
207
208impl_handler!(; A1);
209impl_handler!(A1; A2);
210impl_handler!(A1, A2; A3);
211impl_handler!(A1, A2, A3; A4);
212impl_handler!(A1, A2, A3, A4; A5);
213impl_handler!(A1, A2, A3, A4, A5; A6);
214impl_handler!(A1, A2, A3, A4, A5, A6; A7);
215impl_handler!(A1, A2, A3, A4, A5, A6, A7; A8);
216impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8; A9);
217impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9; A10);
218impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10; A11);
219impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11; A12);
220impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12; A13);
221impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13; A14);
222impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14; A15);
223impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15; A16);
224
225#[cfg(test)]
226mod tests {
227 #![allow(clippy::unwrap_used)]
228 use super::*;
229
230 struct FailParts;
231 impl<S> FromRequestParts<S> for FailParts {
232 type Rejection = crate::http::error::Error;
233 fn from_request_parts(
234 _parts: &mut hyper::http::request::Parts,
235 _state: &S,
236 ) -> Result<Self, Self::Rejection> {
237 Err(crate::http::error::Error::Rejection {
238 status: hyper::StatusCode::BAD_REQUEST,
239 message: "parts fail".to_string(),
240 })
241 }
242 }
243
244 struct FailReq;
245 impl<S: Sync> FromRequest<S> for FailReq {
246 type Rejection = crate::http::error::Error;
247 async fn from_request(_req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
248 Err(crate::http::error::Error::Rejection {
249 status: hyper::StatusCode::BAD_REQUEST,
250 message: "req fail".to_string(),
251 })
252 }
253 }
254
255 struct SucceedParts;
256 impl<S> FromRequestParts<S> for SucceedParts {
257 type Rejection = crate::http::error::Error;
258 fn from_request_parts(
259 _parts: &mut hyper::http::request::Parts,
260 _state: &S,
261 ) -> Result<Self, Self::Rejection> {
262 Ok(Self)
263 }
264 }
265
266 struct SucceedReq;
267 impl<S: Sync> FromRequest<S> for SucceedReq {
268 type Rejection = crate::http::error::Error;
269 async fn from_request(_req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
270 Ok(Self)
271 }
272 }
273
274 #[tokio::test]
275 async fn test_handler_failures() {
276 async fn h1(_p: FailParts, _r: FailReq) -> &'static str {
277 "ok"
278 }
279
280 let req = Request::builder().body(Body::empty()).unwrap();
281 let fut = h1.call(req, Arc::new(()));
282 let res = fut.await;
283 assert_eq!(res.status(), hyper::StatusCode::BAD_REQUEST);
284 }
285
286 #[tokio::test]
287 async fn test_arity0_async_handler_runs_side_effects_exactly_once() {
288 use std::sync::atomic::{AtomicUsize, Ordering};
289 static CALLS: AtomicUsize = AtomicUsize::new(0);
290
291 async fn probe() -> &'static str {
292 CALLS.fetch_add(1, Ordering::SeqCst);
293 tokio::task::yield_now().await;
294 "ok"
295 }
296
297 let req = Request::builder().body(Body::empty()).unwrap();
298 let fut = probe.call(req, Arc::new(()));
299 let res = fut.await;
300 assert_eq!(res.status(), hyper::StatusCode::OK);
301 assert_eq!(
302 CALLS.load(Ordering::SeqCst),
303 1,
304 "handler body ran more than once for a single request"
305 );
306 }
307
308 #[test]
309 fn response_future_debug_does_not_panic() {
310 let ready = ResponseFuture::Ready(Some(Response::new(Body::empty())));
311 assert!(format!("{ready:?}").contains("Ready"));
312
313 let boxed = ResponseFuture::Boxed(Box::pin(async { Response::new(Body::empty()) }));
314 assert!(format!("{boxed:?}").contains("Boxed"));
315 }
316
317 #[tokio::test]
321 async fn test_handler_succeeds_on_parts_then_fails_on_last_extractor() {
322 async fn h(_p: SucceedParts, _r: FailReq) -> &'static str {
323 "unreachable"
324 }
325
326 let req = Request::builder().body(Body::empty()).unwrap();
327 let res = h.call(req, Arc::new(())).await;
328 assert_eq!(res.status(), hyper::StatusCode::BAD_REQUEST);
329 }
330
331 #[tokio::test]
332 async fn test_async_handler_with_all_extractors_succeeding() {
333 async fn h(_p: SucceedParts, _r: SucceedReq) -> &'static str {
334 "ok"
335 }
336
337 let req = Request::builder().body(Body::empty()).unwrap();
338 let res = h.call(req, Arc::new(())).await;
339 assert_eq!(res.status(), hyper::StatusCode::OK);
340 }
341
342 #[tokio::test]
345 async fn test_sync_handler_fails_on_parts_extractor() {
346 fn h(_p: FailParts, _r: SucceedReq) -> &'static str {
347 "unreachable"
348 }
349
350 let req = Request::builder().body(Body::empty()).unwrap();
351 let res = h.call(req, Arc::new(())).await;
352 assert_eq!(res.status(), hyper::StatusCode::BAD_REQUEST);
353 }
354
355 #[tokio::test]
358 async fn test_sync_handler_fails_on_last_extractor() {
359 fn h(_p: SucceedParts, _r: FailReq) -> &'static str {
360 "unreachable"
361 }
362
363 let req = Request::builder().body(Body::empty()).unwrap();
364 let res = h.call(req, Arc::new(())).await;
365 assert_eq!(res.status(), hyper::StatusCode::BAD_REQUEST);
366 }
367
368 #[tokio::test]
369 async fn test_sync_handler_with_all_extractors_succeeding() {
370 fn h(_p: SucceedParts, _r: SucceedReq) -> &'static str {
371 "ok"
372 }
373
374 let req = Request::builder().body(Body::empty()).unwrap();
375 let res = h.call(req, Arc::new(())).await;
376 assert_eq!(res.status(), hyper::StatusCode::OK);
377 }
378}