use std::marker::PhantomData; use actix_http::{Error, Response}; use actix_service::{NewService, Service, Void}; use futures::future::{ok, FutureResult}; use futures::{try_ready, Async, Future, IntoFuture, Poll}; use crate::request::HttpRequest; use crate::responder::Responder; use crate::service::{ServiceRequest, ServiceResponse}; /// Trait implemented by types that can be extracted from request. /// /// Types that implement this trait can be used with `Route` handlers. pub trait FromRequest

: Sized { /// The associated error which can be returned. type Error: Into; /// Future that resolves to a Self type Future: Future; /// Convert request to a Self fn from_request(req: &mut ServiceRequest

) -> Self::Future; } /// Handler converter factory pub trait Factory: Clone where R: Responder, { fn call(&self, param: T) -> R; } impl Factory<(), R> for F where F: Fn() -> R + Clone + 'static, R: Responder + 'static, { fn call(&self, _: ()) -> R { (self)() } } #[doc(hidden)] pub struct Handle where F: Factory, R: Responder, { hnd: F, _t: PhantomData<(T, R)>, } impl Handle where F: Factory, R: Responder, { pub fn new(hnd: F) -> Self { Handle { hnd, _t: PhantomData, } } } impl NewService for Handle where F: Factory, R: Responder + 'static, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; type InitError = (); type Service = HandleService; type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { ok(HandleService { hnd: self.hnd.clone(), _t: PhantomData, }) } } #[doc(hidden)] pub struct HandleService where F: Factory, R: Responder + 'static, { hnd: F, _t: PhantomData<(T, R)>, } impl Service for HandleService where F: Factory, R: Responder + 'static, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; type Future = HandleServiceResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future { let fut = self.hnd.call(param).respond_to(&req); HandleServiceResponse { fut, req: Some(req), } } } pub struct HandleServiceResponse { fut: T, req: Option, } impl Future for HandleServiceResponse where T: Future, T::Error: Into, { type Item = ServiceResponse; type Error = Void; fn poll(&mut self) -> Poll { match self.fut.poll() { Ok(Async::Ready(res)) => Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res, ))), Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { let res: Response = e.into().into(); Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res, ))) } } } } /// Async handler converter factory pub trait AsyncFactory: Clone + 'static where R: IntoFuture, R::Item: Into, R::Error: Into, { fn call(&self, param: T) -> R; } impl AsyncFactory<(), R> for F where F: Fn() -> R + Clone + 'static, R: IntoFuture, R::Item: Into, R::Error: Into, { fn call(&self, _: ()) -> R { (self)() } } #[doc(hidden)] pub struct AsyncHandle where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { hnd: F, _t: PhantomData<(T, R)>, } impl AsyncHandle where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { pub fn new(hnd: F) -> Self { AsyncHandle { hnd, _t: PhantomData, } } } impl NewService for AsyncHandle where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = (); type InitError = (); type Service = AsyncHandleService; type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { ok(AsyncHandleService { hnd: self.hnd.clone(), _t: PhantomData, }) } } #[doc(hidden)] pub struct AsyncHandleService where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { hnd: F, _t: PhantomData<(T, R)>, } impl Service for AsyncHandleService where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = (); type Future = AsyncHandleServiceResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future { AsyncHandleServiceResponse { fut: self.hnd.call(param).into_future(), req: Some(req), } } } #[doc(hidden)] pub struct AsyncHandleServiceResponse { fut: T, req: Option, } impl Future for AsyncHandleServiceResponse where T: Future, T::Item: Into, T::Error: Into, { type Item = ServiceResponse; type Error = (); fn poll(&mut self) -> Poll { match self.fut.poll() { Ok(Async::Ready(res)) => Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res.into(), ))), Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { let res: Response = e.into().into(); Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res, ))) } } } } /// Extract arguments from request pub struct Extract> { _t: PhantomData<(P, T)>, } impl> Extract { pub fn new() -> Self { Extract { _t: PhantomData } } } impl> Default for Extract { fn default() -> Self { Self::new() } } impl> NewService for Extract { type Request = ServiceRequest

; type Response = (T, HttpRequest); type Error = (Error, ServiceRequest

); type InitError = (); type Service = ExtractService; type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { ok(ExtractService { _t: PhantomData }) } } pub struct ExtractService> { _t: PhantomData<(P, T)>, } impl> Service for ExtractService { type Request = ServiceRequest

; type Response = (T, HttpRequest); type Error = (Error, ServiceRequest

); type Future = ExtractResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, mut req: ServiceRequest

) -> Self::Future { ExtractResponse { fut: T::from_request(&mut req), req: Some(req), } } } pub struct ExtractResponse> { req: Option>, fut: T::Future, } impl> Future for ExtractResponse { type Item = (T, HttpRequest); type Error = (Error, ServiceRequest

); fn poll(&mut self) -> Poll { let item = try_ready!(self .fut .poll() .map_err(|e| (e.into(), self.req.take().unwrap()))); let req = self.req.take().unwrap(); let req = req.into_request(); Ok(Async::Ready((item, req))) } } /// FromRequest trait impl for tuples macro_rules! factory_tuple ({ $(($n:tt, $T:ident)),+} => { impl Factory<($($T,)+), Res> for Func where Func: Fn($($T,)+) -> Res + Clone + 'static, //$($T,)+ Res: Responder + 'static, { fn call(&self, param: ($($T,)+)) -> Res { (self)($(param.$n,)+) } } impl AsyncFactory<($($T,)+), Res> for Func where Func: Fn($($T,)+) -> Res + Clone + 'static, Res: IntoFuture + 'static, Res::Item: Into, Res::Error: Into, { fn call(&self, param: ($($T,)+)) -> Res { (self)($(param.$n,)+) } } }); #[rustfmt::skip] mod m { use super::*; factory_tuple!((0, A)); factory_tuple!((0, A), (1, B)); factory_tuple!((0, A), (1, B), (2, C)); factory_tuple!((0, A), (1, B), (2, C), (3, D)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J)); }