use std::marker::PhantomData; use std::net; use actix_net::server; use actix_net::service::{NewService, NewServiceExt, Service}; use futures::future::{ok, FutureResult}; use futures::{Async, Poll}; use tokio_tcp::TcpStream; use super::handler::IntoHttpHandler; use super::service::HttpService; use super::{IoStream, KeepAlive}; pub(crate) trait ServiceFactory where H: IntoHttpHandler, { fn register(&self, server: server::Server, lst: net::TcpListener) -> server::Server; } pub struct HttpServiceBuilder where F: Fn() -> H + Send + Clone, { factory: F, acceptor: A, pipeline: P, } impl HttpServiceBuilder where F: Fn() -> H + Send + Clone, H: IntoHttpHandler, A: AcceptorServiceFactory, P: HttpPipelineFactory, { pub fn new(factory: F, acceptor: A, pipeline: P) -> Self { Self { factory, pipeline, acceptor, } } pub fn acceptor(self, acceptor: A1) -> HttpServiceBuilder where A1: AcceptorServiceFactory, { HttpServiceBuilder { acceptor, pipeline: self.pipeline, factory: self.factory.clone(), } } pub fn pipeline(self, pipeline: P1) -> HttpServiceBuilder where P1: HttpPipelineFactory, { HttpServiceBuilder { pipeline, acceptor: self.acceptor, factory: self.factory.clone(), } } fn finish(&self) -> impl server::StreamServiceFactory { let pipeline = self.pipeline.clone(); let acceptor = self.acceptor.clone(); move || acceptor.create().and_then(pipeline.create()) } } impl Clone for HttpServiceBuilder where F: Fn() -> H + Send + Clone, A: AcceptorServiceFactory, P: HttpPipelineFactory, { fn clone(&self) -> Self { HttpServiceBuilder { factory: self.factory.clone(), acceptor: self.acceptor.clone(), pipeline: self.pipeline.clone(), } } } impl ServiceFactory for HttpServiceBuilder where F: Fn() -> H + Send + Clone, A: AcceptorServiceFactory, P: HttpPipelineFactory, H: IntoHttpHandler, { fn register(&self, server: server::Server, lst: net::TcpListener) -> server::Server { server.listen("actix-web", lst, self.finish()) } } pub trait AcceptorServiceFactory: Send + Clone + 'static { type Io: IoStream + Send; type NewService: NewService< Request = TcpStream, Response = Self::Io, Error = (), InitError = (), >; fn create(&self) -> Self::NewService; } impl AcceptorServiceFactory for F where F: Fn() -> T + Send + Clone + 'static, T::Response: IoStream + Send, T: NewService, { type Io = T::Response; type NewService = T; fn create(&self) -> T { (self)() } } pub trait HttpPipelineFactory: Send + Clone + 'static { type Io: IoStream; type NewService: NewService< Request = Self::Io, Response = (), Error = (), InitError = (), >; fn create(&self) -> Self::NewService; } impl HttpPipelineFactory for F where F: Fn() -> T + Send + Clone + 'static, T: NewService, T::Request: IoStream, { type Io = T::Request; type NewService = T; fn create(&self) -> T { (self)() } } pub(crate) struct DefaultPipelineFactory where F: Fn() -> H + Send + Clone, { factory: F, host: Option, addr: net::SocketAddr, keep_alive: KeepAlive, _t: PhantomData, } impl DefaultPipelineFactory where Io: IoStream + Send, F: Fn() -> H + Send + Clone + 'static, H: IntoHttpHandler + 'static, { pub fn new( factory: F, host: Option, addr: net::SocketAddr, keep_alive: KeepAlive, ) -> Self { Self { factory, addr, keep_alive, host, _t: PhantomData, } } } impl Clone for DefaultPipelineFactory where Io: IoStream, F: Fn() -> H + Send + Clone, H: IntoHttpHandler, { fn clone(&self) -> Self { Self { factory: self.factory.clone(), addr: self.addr, keep_alive: self.keep_alive, host: self.host.clone(), _t: PhantomData, } } } impl HttpPipelineFactory for DefaultPipelineFactory where Io: IoStream + Send, F: Fn() -> H + Send + Clone + 'static, H: IntoHttpHandler + 'static, { type Io = Io; type NewService = HttpService; fn create(&self) -> Self::NewService { HttpService::new( self.factory.clone(), self.addr, self.host.clone(), self.keep_alive, ) } } #[derive(Clone)] pub(crate) struct DefaultAcceptor; impl AcceptorServiceFactory for DefaultAcceptor { type Io = TcpStream; type NewService = DefaultAcceptor; fn create(&self) -> Self::NewService { DefaultAcceptor } } impl NewService for DefaultAcceptor { type Request = TcpStream; type Response = TcpStream; type Error = (); type InitError = (); type Service = DefaultAcceptor; type Future = FutureResult; fn new_service(&self) -> Self::Future { ok(DefaultAcceptor) } } impl Service for DefaultAcceptor { type Request = TcpStream; type Response = TcpStream; type Error = (); type Future = FutureResult; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, req: Self::Request) -> Self::Future { ok(req) } }