use std::future::Future; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; use actix_http::{Error, Response}; use actix_service::{Service, ServiceFactory}; use actix_utils::future::{ready, Ready}; use futures_core::ready; use pin_project::pin_project; use crate::extract::FromRequest; use crate::request::HttpRequest; use crate::responder::Responder; use crate::service::{ServiceRequest, ServiceResponse}; /// A request handler is an async function that accepts zero or more parameters that can be /// extracted from a request (ie, [`impl FromRequest`](crate::FromRequest)) and returns a type that can be converted into /// an [`HttpResponse`](crate::HttpResponse) (ie, [`impl Responder`](crate::Responder)). /// /// If you got the error `the trait Handler<_, _, _> is not implemented`, then your function is not /// a valid handler. See [Request Handlers](https://actix.rs/docs/handlers/) for more information. pub trait Handler: Clone + 'static where R: Future, R::Output: Responder, { fn call(&self, param: T) -> R; } #[doc(hidden)] /// Extract arguments from request, run factory function and make response. pub struct HandlerService where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { hnd: F, _phantom: PhantomData<(T, R)>, } impl HandlerService where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { pub fn new(hnd: F) -> Self { Self { hnd, _phantom: PhantomData, } } } impl Clone for HandlerService where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { fn clone(&self) -> Self { Self { hnd: self.hnd.clone(), _phantom: PhantomData, } } } impl ServiceFactory for HandlerService where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { type Response = ServiceResponse; type Error = Error; type Config = (); type Service = Self; type InitError = (); type Future = Ready>; fn new_service(&self, _: ()) -> Self::Future { ready(Ok(self.clone())) } } /// HandlerService is both it's ServiceFactory and Service Type. impl Service for HandlerService where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { type Response = ServiceResponse; type Error = Error; type Future = HandlerServiceFuture; fn poll_ready(&self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&self, req: ServiceRequest) -> Self::Future { let (req, mut payload) = req.into_parts(); let fut = T::from_request(&req, &mut payload); HandlerServiceFuture::Extract(fut, Some(req), self.hnd.clone()) } } #[doc(hidden)] #[pin_project(project = HandlerProj)] pub enum HandlerServiceFuture where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { Extract(#[pin] T::Future, Option, F), Handle(#[pin] R, Option), } impl Future for HandlerServiceFuture where F: Handler, T: FromRequest, R: Future, R::Output: Responder, { // Error type in this future is a placeholder type. // all instances of error must be converted to ServiceResponse and return in Ok. type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { loop { match self.as_mut().project() { HandlerProj::Extract(fut, req, handle) => { match ready!(fut.poll(cx)) { Ok(item) => { let fut = handle.call(item); let state = HandlerServiceFuture::Handle(fut, req.take()); self.as_mut().set(state); } Err(e) => { let res: Response = e.into().into(); let req = req.take().unwrap(); return Poll::Ready(Ok(ServiceResponse::new(req, res))); } }; } HandlerProj::Handle(fut, req) => { let res = ready!(fut.poll(cx)); let req = req.take().unwrap(); let res = res.respond_to(&req); return Poll::Ready(Ok(ServiceResponse::new(req, res))); } } } } } /// FromRequest trait impl for tuples macro_rules! factory_tuple ({ $($param:ident)* } => { impl Handler<($($param,)*), Res> for Func where Func: Fn($($param),*) -> Res + Clone + 'static, Res: Future, Res::Output: Responder, { #[allow(non_snake_case)] fn call(&self, ($($param,)*): ($($param,)*)) -> Res { (self)($($param,)*) } } }); factory_tuple! {} factory_tuple! { A } factory_tuple! { A B } factory_tuple! { A B C } factory_tuple! { A B C D } factory_tuple! { A B C D E } factory_tuple! { A B C D E F } factory_tuple! { A B C D E F G } factory_tuple! { A B C D E F G H } factory_tuple! { A B C D E F G H I } factory_tuple! { A B C D E F G H I J } factory_tuple! { A B C D E F G H I J K } factory_tuple! { A B C D E F G H I J K L }