use std::cell::RefCell; use std::marker::PhantomData; use std::rc::Rc; use actix_http::{Error, Extensions, 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::{ServiceFromRequest, 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; /// Configuration for the extractor type Config: ExtractorConfig; /// Convert request to a Self fn from_request(req: &mut ServiceFromRequest

) -> Self::Future; } /// Storage for extractor configs #[derive(Default)] pub struct ConfigStorage { pub(crate) storage: Option>, } impl ConfigStorage { pub fn store(&mut self, config: C) { if self.storage.is_none() { self.storage = Some(Rc::new(Extensions::new())); } if let Some(ref mut ext) = self.storage { Rc::get_mut(ext).unwrap().insert(config); } } } pub trait ExtractorConfig: Default + Clone + 'static { /// Set default configuration to config storage fn store_default(ext: &mut ConfigStorage) { ext.store(Self::default()) } } impl ExtractorConfig for () { fn store_default(_: &mut ConfigStorage) {} } /// 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> { config: Rc>>>, _t: PhantomData<(P, T)>, } impl> Extract { pub fn new(config: Rc>>>) -> Self { Extract { config, _t: PhantomData, } } } impl> NewService for Extract { type Request = ServiceRequest

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

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

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

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

) -> Self::Future { let mut req = ServiceFromRequest::new(req, self.config.clone()); 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, ServiceFromRequest

); 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, 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)); }