diff --git a/Cargo.toml b/Cargo.toml index 5e2027c5..dbc0a65d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ actix-utils = { git = "https://github.com/actix/actix-net.git" } actix-http = { git = "https://github.com/actix/actix-http.git" } actix-router = { git = "https://github.com/actix/actix-net.git" } actix-server = { git = "https://github.com/actix/actix-net.git" } -#actix-router = { path="../actix-net/router" } +actix-server-config = { git = "https://github.com/actix/actix-net.git" } bytes = "0.4" derive_more = "0.14" diff --git a/src/app.rs b/src/app.rs index b4f6e535..76a3a1ce 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,37 +3,30 @@ use std::marker::PhantomData; use std::rc::Rc; use actix_http::body::{Body, MessageBody}; -use actix_http::{Extensions, PayloadStream, Request, Response}; -use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url}; -use actix_service::boxed::{self, BoxedNewService, BoxedService}; +use actix_http::{Extensions, PayloadStream}; +use actix_server_config::ServerConfig; +use actix_service::boxed::{self, BoxedNewService}; use actix_service::{ - fn_service, AndThenNewService, ApplyTransform, IntoNewService, IntoTransform, - NewService, Service, Transform, + ApplyTransform, IntoNewService, IntoTransform, NewService, Transform, }; -use futures::future::{ok, Either, FutureResult}; -use futures::{Async, Future, IntoFuture, Poll}; +use futures::IntoFuture; -use crate::config::AppConfig; -use crate::guard::Guard; +use crate::app_service::{AppChain, AppEntry, AppInit, AppRouting, AppRoutingFactory}; use crate::resource::Resource; -use crate::rmap::ResourceMap; use crate::route::Route; use crate::service::{ HttpServiceFactory, ServiceFactory, ServiceFactoryWrapper, ServiceRequest, ServiceResponse, }; -use crate::state::{State, StateFactory, StateFactoryResult}; +use crate::state::{State, StateFactory}; -type Guards = Vec>; -type HttpService

= BoxedService, ServiceResponse, ()>; type HttpNewService

= BoxedNewService<(), ServiceRequest

, ServiceResponse, (), ()>; -type BoxedResponse = Box>; /// Application builder - structure that follows the builder pattern /// for building application instances. pub struct App where - T: NewService>, + T: NewService>, { chain: T, extensions: Extensions, @@ -58,7 +51,7 @@ impl App where P: 'static, T: NewService< - ServiceRequest, + Request = ServiceRequest, Response = ServiceRequest

, Error = (), InitError = (), @@ -121,7 +114,7 @@ where P, B, impl NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -130,12 +123,12 @@ where where M: Transform< AppRouting

, - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), >, - F: IntoTransform, ServiceRequest

>, + F: IntoTransform>, { let fref = Rc::new(RefCell::new(None)); let endpoint = ApplyTransform::new(mw, AppEntry::new(fref.clone())); @@ -159,7 +152,7 @@ where ) -> App< P1, impl NewService< - ServiceRequest, + Request = ServiceRequest, Response = ServiceRequest, Error = (), InitError = (), @@ -167,12 +160,12 @@ where > where C: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceRequest, Error = (), InitError = (), >, - F: IntoNewService>, + F: IntoNewService, { let chain = self.chain.and_then(chain.into_new_service()); App { @@ -264,7 +257,7 @@ where P: 'static, B: MessageBody, T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -324,7 +317,7 @@ where P, B1, impl NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -333,13 +326,13 @@ where where M: Transform< T::Service, - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), >, B1: MessageBody, - F: IntoTransform>, + F: IntoTransform, { let endpoint = ApplyTransform::new(mw, self.endpoint); AppRouter { @@ -362,7 +355,7 @@ where where F: FnOnce(Resource

) -> Resource, U: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -413,391 +406,39 @@ where } } -impl - IntoNewService, T>, Request> +impl IntoNewService, ServerConfig> for AppRouter where T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), >, C: NewService< - ServiceRequest, + Request = ServiceRequest, Response = ServiceRequest

, Error = (), InitError = (), >, { - fn into_new_service(self) -> AndThenNewService, T> { - // update resource default service - let default = self.default.unwrap_or_else(|| { - Rc::new(boxed::new_service(fn_service(|req: ServiceRequest

| { - Ok(req.into_response(Response::NotFound().finish())) - }))) - }); - - let mut config = AppConfig::new( - "127.0.0.1:8080".parse().unwrap(), - "localhost:8080".to_owned(), - false, - default.clone(), - ); - - // register services - self.services - .into_iter() - .for_each(|mut srv| srv.register(&mut config)); - - let mut rmap = ResourceMap::new(ResourceDef::new("")); - - // complete pipeline creation - *self.factory_ref.borrow_mut() = Some(AppRoutingFactory { - default, - services: Rc::new( - config - .into_services() - .into_iter() - .map(|(mut rdef, srv, guards, nested)| { - rmap.add(&mut rdef, nested); - (rdef, srv, RefCell::new(guards)) - }) - .collect(), - ), - }); - - // complete ResourceMap tree creation - let rmap = Rc::new(rmap); - rmap.finish(rmap.clone()); - + fn into_new_service(self) -> AppInit { AppInit { - rmap, chain: self.chain, state: self.state, + endpoint: self.endpoint, + services: RefCell::new(self.services), + default: self.default, + factory_ref: self.factory_ref, extensions: Rc::new(RefCell::new(Rc::new(self.extensions))), } - .and_then(self.endpoint) - } -} - -pub struct AppRoutingFactory

{ - services: Rc, RefCell>)>>, - default: Rc>, -} - -impl NewService> for AppRoutingFactory

{ - type Response = ServiceResponse; - type Error = (); - type InitError = (); - type Service = AppRouting

; - type Future = AppRoutingFactoryResponse

; - - fn new_service(&self, _: &()) -> Self::Future { - AppRoutingFactoryResponse { - fut: self - .services - .iter() - .map(|(path, service, guards)| { - CreateAppRoutingItem::Future( - Some(path.clone()), - guards.borrow_mut().take(), - service.new_service(&()), - ) - }) - .collect(), - default: None, - default_fut: Some(self.default.new_service(&())), - } - } -} - -type HttpServiceFut

= Box, Error = ()>>; - -/// Create app service -#[doc(hidden)] -pub struct AppRoutingFactoryResponse

{ - fut: Vec>, - default: Option>, - default_fut: Option, Error = ()>>>, -} - -enum CreateAppRoutingItem

{ - Future(Option, Option, HttpServiceFut

), - Service(ResourceDef, Option, HttpService

), -} - -impl

Future for AppRoutingFactoryResponse

{ - type Item = AppRouting

; - type Error = (); - - fn poll(&mut self) -> Poll { - let mut done = true; - - if let Some(ref mut fut) = self.default_fut { - match fut.poll()? { - Async::Ready(default) => self.default = Some(default), - Async::NotReady => done = false, - } - } - - // poll http services - for item in &mut self.fut { - let res = match item { - CreateAppRoutingItem::Future( - ref mut path, - ref mut guards, - ref mut fut, - ) => match fut.poll()? { - Async::Ready(service) => { - Some((path.take().unwrap(), guards.take(), service)) - } - Async::NotReady => { - done = false; - None - } - }, - CreateAppRoutingItem::Service(_, _, _) => continue, - }; - - if let Some((path, guards, service)) = res { - *item = CreateAppRoutingItem::Service(path, guards, service); - } - } - - if done { - let router = self - .fut - .drain(..) - .fold(Router::build(), |mut router, item| { - match item { - CreateAppRoutingItem::Service(path, guards, service) => { - router.rdef(path, service).2 = guards; - } - CreateAppRoutingItem::Future(_, _, _) => unreachable!(), - } - router - }); - Ok(Async::Ready(AppRouting { - ready: None, - router: router.finish(), - default: self.default.take(), - })) - } else { - Ok(Async::NotReady) - } - } -} - -pub struct AppRouting

{ - router: Router, Guards>, - ready: Option<(ServiceRequest

, ResourceInfo)>, - default: Option>, -} - -impl

Service> for AppRouting

{ - type Response = ServiceResponse; - type Error = (); - type Future = Either>; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - if self.ready.is_none() { - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - } - - fn call(&mut self, mut req: ServiceRequest

) -> Self::Future { - let res = self.router.recognize_mut_checked(&mut req, |req, guards| { - if let Some(ref guards) = guards { - for f in guards { - if !f.check(req.head()) { - return false; - } - } - } - true - }); - - if let Some((srv, _info)) = res { - Either::A(srv.call(req)) - } else if let Some(ref mut default) = self.default { - Either::A(default.call(req)) - } else { - let req = req.into_request(); - Either::B(ok(ServiceResponse::new(req, Response::NotFound().finish()))) - } - } -} - -#[doc(hidden)] -/// Wrapper service for routing -pub struct AppEntry

{ - factory: Rc>>>, -} - -impl

AppEntry

{ - fn new(factory: Rc>>>) -> Self { - AppEntry { factory } - } -} - -impl NewService> for AppEntry

{ - type Response = ServiceResponse; - type Error = (); - type InitError = (); - type Service = AppRouting

; - type Future = AppRoutingFactoryResponse

; - - fn new_service(&self, _: &()) -> Self::Future { - self.factory.borrow_mut().as_mut().unwrap().new_service(&()) - } -} - -#[doc(hidden)] -pub struct AppChain; - -impl NewService for AppChain { - type Response = ServiceRequest; - type Error = (); - type InitError = (); - type Service = AppChain; - type Future = FutureResult; - - fn new_service(&self, _: &()) -> Self::Future { - ok(AppChain) - } -} - -impl Service for AppChain { - type Response = ServiceRequest; - type Error = (); - type Future = FutureResult; - - #[inline] - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(Async::Ready(())) - } - - #[inline] - fn call(&mut self, req: ServiceRequest) -> Self::Future { - ok(req) - } -} - -/// Service factory to convert `Request` to a `ServiceRequest`. -/// It also executes state factories. -pub struct AppInit -where - C: NewService>, -{ - chain: C, - rmap: Rc, - state: Vec>, - extensions: Rc>>, -} - -impl NewService for AppInit -where - C: NewService, InitError = ()>, -{ - type Response = ServiceRequest

; - type Error = C::Error; - type InitError = C::InitError; - type Service = AppInitService; - type Future = AppInitResult; - - fn new_service(&self, _: &()) -> Self::Future { - AppInitResult { - chain: self.chain.new_service(&()), - state: self.state.iter().map(|s| s.construct()).collect(), - extensions: self.extensions.clone(), - rmap: self.rmap.clone(), - } - } -} - -#[doc(hidden)] -pub struct AppInitResult -where - C: NewService, InitError = ()>, -{ - chain: C::Future, - rmap: Rc, - state: Vec>, - extensions: Rc>>, -} - -impl Future for AppInitResult -where - C: NewService, InitError = ()>, -{ - type Item = AppInitService; - type Error = C::InitError; - - fn poll(&mut self) -> Poll { - if let Some(extensions) = Rc::get_mut(&mut *self.extensions.borrow_mut()) { - let mut idx = 0; - while idx < self.state.len() { - if let Async::Ready(_) = self.state[idx].poll_result(extensions)? { - self.state.remove(idx); - } else { - idx += 1; - } - } - if !self.state.is_empty() { - return Ok(Async::NotReady); - } - } else { - log::warn!("Multiple copies of app extensions exists"); - } - - let chain = futures::try_ready!(self.chain.poll()); - - Ok(Async::Ready(AppInitService { - chain, - rmap: self.rmap.clone(), - extensions: self.extensions.borrow().clone(), - })) - } -} - -/// Service to convert `Request` to a `ServiceRequest` -pub struct AppInitService -where - C: Service>, -{ - chain: C, - rmap: Rc, - extensions: Rc, -} - -impl Service for AppInitService -where - C: Service>, -{ - type Response = ServiceRequest

; - type Error = C::Error; - type Future = C::Future; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.chain.poll_ready() - } - - fn call(&mut self, req: Request) -> Self::Future { - let req = ServiceRequest::new( - Path::new(Url::new(req.uri().clone())), - req, - self.rmap.clone(), - self.extensions.clone(), - ); - self.chain.call(req) } } #[cfg(test)] mod tests { + use actix_service::Service; + use super::*; use crate::http::{Method, StatusCode}; use crate::test::{block_on, init_service, TestRequest}; diff --git a/src/app_service.rs b/src/app_service.rs new file mode 100644 index 00000000..094486d9 --- /dev/null +++ b/src/app_service.rs @@ -0,0 +1,439 @@ +use std::cell::RefCell; +use std::marker::PhantomData; +use std::rc::Rc; + +use actix_http::{Extensions, Request, Response}; +use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url}; +use actix_server_config::ServerConfig; +use actix_service::boxed::{self, BoxedNewService, BoxedService}; +use actix_service::{fn_service, AndThen, NewService, Service, ServiceExt}; +use futures::future::{ok, Either, FutureResult}; +use futures::{Async, Future, Poll}; + +use crate::config::AppConfig; +use crate::guard::Guard; +use crate::rmap::ResourceMap; +use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse}; +use crate::state::{StateFactory, StateFactoryResult}; + +type Guards = Vec>; +type HttpService

= BoxedService, ServiceResponse, ()>; +type HttpNewService

= BoxedNewService<(), ServiceRequest

, ServiceResponse, (), ()>; +type BoxedResponse = Box>; + +/// Service factory to convert `Request` to a `ServiceRequest`. +/// It also executes state factories. +pub struct AppInit +where + C: NewService>, + T: NewService< + Request = ServiceRequest

, + Response = ServiceResponse, + Error = (), + InitError = (), + >, +{ + pub(crate) chain: C, + pub(crate) endpoint: T, + pub(crate) state: Vec>, + pub(crate) extensions: Rc>>, + pub(crate) services: RefCell>>>, + pub(crate) default: Option>>, + pub(crate) factory_ref: Rc>>>, +} + +impl NewService for AppInit +where + C: NewService< + Request = ServiceRequest, + Response = ServiceRequest

, + Error = (), + InitError = (), + >, + T: NewService< + Request = ServiceRequest

, + Response = ServiceResponse, + Error = (), + InitError = (), + >, +{ + type Request = Request; + type Response = ServiceResponse; + type Error = C::Error; + type InitError = C::InitError; + type Service = AndThen, T::Service>; + type Future = AppInitResult; + + fn new_service(&self, _: &ServerConfig) -> Self::Future { + // update resource default service + let default = self.default.clone().unwrap_or_else(|| { + Rc::new(boxed::new_service(fn_service(|req: ServiceRequest

| { + Ok(req.into_response(Response::NotFound().finish())) + }))) + }); + + let mut config = AppConfig::new( + "127.0.0.1:8080".parse().unwrap(), + "localhost:8080".to_owned(), + false, + default.clone(), + ); + + // register services + std::mem::replace(&mut *self.services.borrow_mut(), Vec::new()) + .into_iter() + .for_each(|mut srv| srv.register(&mut config)); + + let mut rmap = ResourceMap::new(ResourceDef::new("")); + + // complete pipeline creation + *self.factory_ref.borrow_mut() = Some(AppRoutingFactory { + default, + services: Rc::new( + config + .into_services() + .into_iter() + .map(|(mut rdef, srv, guards, nested)| { + rmap.add(&mut rdef, nested); + (rdef, srv, RefCell::new(guards)) + }) + .collect(), + ), + }); + + // complete ResourceMap tree creation + let rmap = Rc::new(rmap); + rmap.finish(rmap.clone()); + + AppInitResult { + chain: None, + chain_fut: self.chain.new_service(&()), + endpoint: None, + endpoint_fut: self.endpoint.new_service(&()), + state: self.state.iter().map(|s| s.construct()).collect(), + extensions: self.extensions.clone(), + rmap, + _t: PhantomData, + } + } +} + +pub struct AppInitResult +where + C: NewService, + T: NewService, +{ + chain: Option, + endpoint: Option, + chain_fut: C::Future, + endpoint_fut: T::Future, + rmap: Rc, + state: Vec>, + extensions: Rc>>, + _t: PhantomData<(P, B)>, +} + +impl Future for AppInitResult +where + C: NewService< + Request = ServiceRequest, + Response = ServiceRequest

, + Error = (), + InitError = (), + >, + T: NewService< + Request = ServiceRequest

, + Response = ServiceResponse, + Error = (), + InitError = (), + >, +{ + type Item = AndThen, T::Service>; + type Error = C::InitError; + + fn poll(&mut self) -> Poll { + if let Some(extensions) = Rc::get_mut(&mut *self.extensions.borrow_mut()) { + let mut idx = 0; + while idx < self.state.len() { + if let Async::Ready(_) = self.state[idx].poll_result(extensions)? { + self.state.remove(idx); + } else { + idx += 1; + } + } + if !self.state.is_empty() { + return Ok(Async::NotReady); + } + } else { + log::warn!("Multiple copies of app extensions exists"); + } + + if self.chain.is_none() { + if let Async::Ready(srv) = self.chain_fut.poll()? { + self.chain = Some(srv); + } + } + + if self.endpoint.is_none() { + if let Async::Ready(srv) = self.endpoint_fut.poll()? { + self.endpoint = Some(srv); + } + } + + if self.chain.is_some() && self.endpoint.is_some() { + Ok(Async::Ready( + AppInitService { + chain: self.chain.take().unwrap(), + rmap: self.rmap.clone(), + extensions: self.extensions.borrow().clone(), + } + .and_then(self.endpoint.take().unwrap()), + )) + } else { + Ok(Async::NotReady) + } + } +} + +/// Service to convert `Request` to a `ServiceRequest` +pub struct AppInitService +where + C: Service, Error = ()>, +{ + chain: C, + rmap: Rc, + extensions: Rc, +} + +impl Service for AppInitService +where + C: Service, Error = ()>, +{ + type Request = Request; + type Response = ServiceRequest

; + type Error = C::Error; + type Future = C::Future; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.chain.poll_ready() + } + + fn call(&mut self, req: Request) -> Self::Future { + let req = ServiceRequest::new( + Path::new(Url::new(req.uri().clone())), + req, + self.rmap.clone(), + self.extensions.clone(), + ); + self.chain.call(req) + } +} + +pub struct AppRoutingFactory

{ + services: Rc, RefCell>)>>, + default: Rc>, +} + +impl NewService for AppRoutingFactory

{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = (); + type InitError = (); + type Service = AppRouting

; + type Future = AppRoutingFactoryResponse

; + + fn new_service(&self, _: &()) -> Self::Future { + AppRoutingFactoryResponse { + fut: self + .services + .iter() + .map(|(path, service, guards)| { + CreateAppRoutingItem::Future( + Some(path.clone()), + guards.borrow_mut().take(), + service.new_service(&()), + ) + }) + .collect(), + default: None, + default_fut: Some(self.default.new_service(&())), + } + } +} + +type HttpServiceFut

= Box, Error = ()>>; + +/// Create app service +#[doc(hidden)] +pub struct AppRoutingFactoryResponse

{ + fut: Vec>, + default: Option>, + default_fut: Option, Error = ()>>>, +} + +enum CreateAppRoutingItem

{ + Future(Option, Option, HttpServiceFut

), + Service(ResourceDef, Option, HttpService

), +} + +impl

Future for AppRoutingFactoryResponse

{ + type Item = AppRouting

; + type Error = (); + + fn poll(&mut self) -> Poll { + let mut done = true; + + if let Some(ref mut fut) = self.default_fut { + match fut.poll()? { + Async::Ready(default) => self.default = Some(default), + Async::NotReady => done = false, + } + } + + // poll http services + for item in &mut self.fut { + let res = match item { + CreateAppRoutingItem::Future( + ref mut path, + ref mut guards, + ref mut fut, + ) => match fut.poll()? { + Async::Ready(service) => { + Some((path.take().unwrap(), guards.take(), service)) + } + Async::NotReady => { + done = false; + None + } + }, + CreateAppRoutingItem::Service(_, _, _) => continue, + }; + + if let Some((path, guards, service)) = res { + *item = CreateAppRoutingItem::Service(path, guards, service); + } + } + + if done { + let router = self + .fut + .drain(..) + .fold(Router::build(), |mut router, item| { + match item { + CreateAppRoutingItem::Service(path, guards, service) => { + router.rdef(path, service).2 = guards; + } + CreateAppRoutingItem::Future(_, _, _) => unreachable!(), + } + router + }); + Ok(Async::Ready(AppRouting { + ready: None, + router: router.finish(), + default: self.default.take(), + })) + } else { + Ok(Async::NotReady) + } + } +} + +pub struct AppRouting

{ + router: Router, Guards>, + ready: Option<(ServiceRequest

, ResourceInfo)>, + default: Option>, +} + +impl

Service for AppRouting

{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = (); + type Future = Either>; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + if self.ready.is_none() { + Ok(Async::Ready(())) + } else { + Ok(Async::NotReady) + } + } + + fn call(&mut self, mut req: ServiceRequest

) -> Self::Future { + let res = self.router.recognize_mut_checked(&mut req, |req, guards| { + if let Some(ref guards) = guards { + for f in guards { + if !f.check(req.head()) { + return false; + } + } + } + true + }); + + if let Some((srv, _info)) = res { + Either::A(srv.call(req)) + } else if let Some(ref mut default) = self.default { + Either::A(default.call(req)) + } else { + let req = req.into_request(); + Either::B(ok(ServiceResponse::new(req, Response::NotFound().finish()))) + } + } +} + +/// Wrapper service for routing +pub struct AppEntry

{ + factory: Rc>>>, +} + +impl

AppEntry

{ + pub fn new(factory: Rc>>>) -> Self { + AppEntry { factory } + } +} + +impl NewService for AppEntry

{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = (); + type InitError = (); + type Service = AppRouting

; + type Future = AppRoutingFactoryResponse

; + + fn new_service(&self, _: &()) -> Self::Future { + self.factory.borrow_mut().as_mut().unwrap().new_service(&()) + } +} + +#[doc(hidden)] +pub struct AppChain; + +impl NewService for AppChain { + type Request = ServiceRequest; + type Response = ServiceRequest; + type Error = (); + type InitError = (); + type Service = AppChain; + type Future = FutureResult; + + fn new_service(&self, _: &()) -> Self::Future { + ok(AppChain) + } +} + +impl Service for AppChain { + type Request = ServiceRequest; + type Response = ServiceRequest; + type Error = (); + type Future = FutureResult; + + #[inline] + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + Ok(Async::Ready(())) + } + + #[inline] + fn call(&mut self, req: ServiceRequest) -> Self::Future { + ok(req) + } +} diff --git a/src/config.rs b/src/config.rs index 4afd213c..47c2f7c4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -98,9 +98,9 @@ impl AppConfig

{ service: F, nested: Option>, ) where - F: IntoNewService>, + F: IntoNewService, S: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), diff --git a/src/handler.rs b/src/handler.rs index 435d9a8b..87645651 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -52,11 +52,12 @@ where } } } -impl NewService<(T, HttpRequest)> for Handler +impl NewService for Handler where F: Factory, R: Responder + 'static, { + type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; type InitError = (); @@ -81,11 +82,12 @@ where _t: PhantomData<(T, R)>, } -impl Service<(T, HttpRequest)> for HandlerService +impl Service for HandlerService where F: Factory, R: Responder + 'static, { + type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; type Future = HandlerServiceResponse<::Future>; @@ -182,13 +184,14 @@ where } } } -impl NewService<(T, HttpRequest)> for AsyncHandler +impl NewService for AsyncHandler where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { + type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = (); type InitError = (); @@ -215,13 +218,14 @@ where _t: PhantomData<(T, R)>, } -impl Service<(T, HttpRequest)> for AsyncHandlerService +impl Service for AsyncHandlerService where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { + type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = (); type Future = AsyncHandlerServiceResponse; @@ -286,7 +290,8 @@ impl> Extract { } } -impl> NewService> for Extract { +impl> NewService for Extract { + type Request = ServiceRequest

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

); type InitError = (); @@ -306,7 +311,8 @@ pub struct ExtractService> { _t: PhantomData<(P, T)>, } -impl> Service> for ExtractService { +impl> Service for ExtractService { + type Request = ServiceRequest

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

); type Future = ExtractResponse; diff --git a/src/lib.rs b/src/lib.rs index 94bf1ba7..19f466b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![allow(clippy::type_complexity)] mod app; +mod app_service; mod extract; mod handler; // mod info; diff --git a/src/middleware/compress.rs b/src/middleware/compress.rs index c6f090a6..b3880a53 100644 --- a/src/middleware/compress.rs +++ b/src/middleware/compress.rs @@ -1,4 +1,5 @@ use std::io::Write; +use std::marker::PhantomData; use std::str::FromStr; use std::{cmp, fmt, io}; @@ -36,13 +37,14 @@ impl Default for Compress { } } -impl Transform> for Compress +impl Transform for Compress where P: 'static, B: MessageBody, - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, S::Future: 'static, { + type Request = ServiceRequest

; type Response = ServiceResponse>; type Error = S::Error; type InitError = (); @@ -62,13 +64,14 @@ pub struct CompressMiddleware { encoding: ContentEncoding, } -impl Service> for CompressMiddleware +impl Service for CompressMiddleware where P: 'static, B: MessageBody, - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, S::Future: 'static, { + type Request = ServiceRequest

; type Response = ServiceResponse>; type Error = S::Error; type Future = CompressResponse; @@ -92,6 +95,7 @@ where CompressResponse { encoding, fut: self.service.call(req), + _t: PhantomData, } } } @@ -101,18 +105,19 @@ pub struct CompressResponse where P: 'static, B: MessageBody, - S: Service, Response = ServiceResponse>, + S: Service, S::Future: 'static, { fut: S::Future, encoding: ContentEncoding, + _t: PhantomData<(P, B)>, } impl Future for CompressResponse where P: 'static, B: MessageBody, - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, S::Future: 'static, { type Item = ServiceResponse>; diff --git a/src/middleware/defaultheaders.rs b/src/middleware/defaultheaders.rs index f4def58d..b4927962 100644 --- a/src/middleware/defaultheaders.rs +++ b/src/middleware/defaultheaders.rs @@ -85,11 +85,12 @@ impl DefaultHeaders { } } -impl Transform> for DefaultHeaders +impl Transform for DefaultHeaders where - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, S::Future: 'static, { + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = S::Error; type InitError = (); @@ -109,11 +110,12 @@ pub struct DefaultHeadersMiddleware { inner: Rc, } -impl Service> for DefaultHeadersMiddleware +impl Service for DefaultHeadersMiddleware where - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, S::Future: 'static, { + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = S::Error; type Future = Box>; diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index d8b4e643..4af3e10d 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use std::env; use std::fmt::{self, Display, Formatter}; +use std::marker::PhantomData; use std::rc::Rc; use actix_service::{Service, Transform}; @@ -110,11 +111,12 @@ impl Default for Logger { } } -impl Transform> for Logger +impl Transform for Logger where - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, B: MessageBody, { + type Request = ServiceRequest

; type Response = ServiceResponse>; type Error = S::Error; type InitError = (); @@ -135,11 +137,12 @@ pub struct LoggerMiddleware { service: S, } -impl Service> for LoggerMiddleware +impl Service for LoggerMiddleware where - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, B: MessageBody, { + type Request = ServiceRequest

; type Response = ServiceResponse>; type Error = S::Error; type Future = LoggerResponse; @@ -154,6 +157,7 @@ where fut: self.service.call(req), format: None, time: time::now(), + _t: PhantomData, } } else { let now = time::now(); @@ -166,6 +170,7 @@ where fut: self.service.call(req), format: Some(format), time: now, + _t: PhantomData, } } } @@ -175,17 +180,18 @@ where pub struct LoggerResponse where B: MessageBody, - S: Service, Response = ServiceResponse>, + S: Service, { fut: S::Future, time: time::Tm, format: Option, + _t: PhantomData<(P, B)>, } impl Future for LoggerResponse where B: MessageBody, - S: Service, Response = ServiceResponse>, + S: Service, Response = ServiceResponse>, { type Item = ServiceResponse>; type Error = S::Error; diff --git a/src/resource.rs b/src/resource.rs index a1177ca0..cc831665 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -66,7 +66,7 @@ impl Resource where P: 'static, T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -220,7 +220,7 @@ where ) -> Resource< P, impl NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -229,12 +229,12 @@ where where M: Transform< T::Service, - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), >, - F: IntoTransform>, + F: IntoTransform, { let endpoint = ApplyTransform::new(mw, self.endpoint); Resource { @@ -251,9 +251,12 @@ where pub fn default_resource(mut self, f: F) -> Self where F: FnOnce(Resource

) -> R, - R: IntoNewService>, - U: NewService, Response = ServiceResponse, Error = ()> - + 'static, + R: IntoNewService, + U: NewService< + Request = ServiceRequest

, + Response = ServiceResponse, + Error = (), + > + 'static, { // create and configure default resource self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service( @@ -268,7 +271,7 @@ impl HttpServiceFactory

for Resource where P: 'static, T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -292,10 +295,10 @@ where } } -impl IntoNewService> for Resource +impl IntoNewService for Resource where T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -316,7 +319,8 @@ pub struct ResourceFactory

{ default: Rc>>>>, } -impl NewService> for ResourceFactory

{ +impl NewService for ResourceFactory

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type InitError = (); @@ -406,7 +410,8 @@ pub struct ResourceService

{ default: Option>, } -impl

Service> for ResourceService

{ +impl

Service for ResourceService

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type Future = Either< @@ -450,7 +455,8 @@ impl

ResourceEndpoint

{ } } -impl NewService> for ResourceEndpoint

{ +impl NewService for ResourceEndpoint

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type InitError = (); diff --git a/src/route.rs b/src/route.rs index f7b99050..c189c61b 100644 --- a/src/route.rs +++ b/src/route.rs @@ -15,7 +15,7 @@ use crate::HttpResponse; type BoxedRouteService = Box< Service< - Req, + Request = Req, Response = Res, Error = (), Future = Box>, @@ -24,7 +24,7 @@ type BoxedRouteService = Box< type BoxedRouteNewService = Box< NewService< - Req, + Request = Req, Response = Res, Error = (), InitError = (), @@ -70,7 +70,8 @@ impl Route

{ } } -impl

NewService> for Route

{ +impl

NewService for Route

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type InitError = (); @@ -125,7 +126,8 @@ impl

RouteService

{ } } -impl

Service> for RouteService

{ +impl

Service for RouteService

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type Future = Box>; @@ -330,7 +332,7 @@ impl Route

{ struct RouteNewService where - T: NewService, Error = (Error, ServiceFromRequest

)>, + T: NewService, Error = (Error, ServiceFromRequest

)>, { service: T, _t: PhantomData

, @@ -339,13 +341,13 @@ where impl RouteNewService where T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (Error, ServiceFromRequest

), >, T::Future: 'static, T::Service: 'static, - >>::Future: 'static, + ::Future: 'static, { pub fn new(service: T) -> Self { RouteNewService { @@ -355,17 +357,18 @@ where } } -impl NewService> for RouteNewService +impl NewService for RouteNewService where T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (Error, ServiceFromRequest

), >, T::Future: 'static, T::Service: 'static, - >>::Future: 'static, + ::Future: 'static, { + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type InitError = (); @@ -389,20 +392,21 @@ where } } -struct RouteServiceWrapper>> { +struct RouteServiceWrapper { service: T, _t: PhantomData

, } -impl Service> for RouteServiceWrapper +impl Service for RouteServiceWrapper where T::Future: 'static, T: Service< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (Error, ServiceFromRequest

), >, { + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type Future = Box>; diff --git a/src/scope.rs b/src/scope.rs index 15c652c8..6c511c69 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -81,7 +81,7 @@ impl Scope where P: 'static, T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -174,7 +174,7 @@ where where F: FnOnce(Resource

) -> Resource, U: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -199,7 +199,7 @@ where ) -> Scope< P, impl NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -208,12 +208,12 @@ where where M: Transform< T::Service, - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), >, - F: IntoTransform>, + F: IntoTransform, { let endpoint = ApplyTransform::new(mw, self.endpoint); Scope { @@ -231,7 +231,7 @@ impl HttpServiceFactory

for Scope where P: 'static, T: NewService< - ServiceRequest

, + Request = ServiceRequest

, Response = ServiceResponse, Error = (), InitError = (), @@ -287,7 +287,8 @@ pub struct ScopeFactory

{ default: Rc>>>>, } -impl NewService> for ScopeFactory

{ +impl NewService for ScopeFactory

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type InitError = (); @@ -402,7 +403,8 @@ pub struct ScopeService

{ _ready: Option<(ServiceRequest

, ResourceInfo)>, } -impl

Service> for ScopeService

{ +impl

Service for ScopeService

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type Future = Either>; @@ -445,7 +447,8 @@ impl

ScopeEndpoint

{ } } -impl NewService> for ScopeEndpoint

{ +impl NewService for ScopeEndpoint

{ + type Request = ServiceRequest

; type Response = ServiceResponse; type Error = (); type InitError = (); diff --git a/src/server.rs b/src/server.rs index d3ae5b2b..d9574365 100644 --- a/src/server.rs +++ b/src/server.rs @@ -7,6 +7,7 @@ use actix_http::{ }; use actix_rt::System; use actix_server::{Server, ServerBuilder}; +use actix_server_config::ServerConfig; use actix_service::{IntoNewService, NewService}; use parking_lot::Mutex; @@ -53,8 +54,8 @@ struct Config { pub struct HttpServer where F: Fn() -> I + Send + Clone + 'static, - I: IntoNewService, - S: NewService, + I: IntoNewService, + S: NewService, S::Error: fmt::Debug, S::Response: Into>, S::Service: 'static, @@ -72,8 +73,8 @@ where impl HttpServer where F: Fn() -> I + Send + Clone + 'static, - I: IntoNewService, - S: NewService, + I: IntoNewService, + S: NewService, S::Error: fmt::Debug + 'static, S::Response: Into>, S::Service: 'static, @@ -432,8 +433,8 @@ where impl HttpServer where F: Fn() -> I + Send + Clone + 'static, - I: IntoNewService, - S: NewService, + I: IntoNewService, + S: NewService, S::Error: fmt::Debug, S::Response: Into>, S::Service: 'static, diff --git a/src/test.rs b/src/test.rs index e4cdefbe..c88835a3 100644 --- a/src/test.rs +++ b/src/test.rs @@ -8,6 +8,7 @@ use actix_http::test::TestRequest as HttpTestRequest; use actix_http::{Extensions, PayloadStream, Request}; use actix_router::{Path, ResourceDef, Url}; use actix_rt::Runtime; +use actix_server_config::ServerConfig; use actix_service::{IntoNewService, NewService, Service}; use bytes::Bytes; use futures::Future; @@ -62,13 +63,19 @@ where /// ``` pub fn init_service( app: R, -) -> impl Service, Error = E> +) -> impl Service, Error = E> where - R: IntoNewService, - S: NewService, Error = E>, + R: IntoNewService, + S: NewService< + ServerConfig, + Request = Request, + Response = ServiceResponse, + Error = E, + >, S::InitError: std::fmt::Debug, { - block_on(app.into_new_service().new_service(&())).unwrap() + let cfg = ServerConfig::new("127.0.0.1:8080".parse().unwrap()); + block_on(app.into_new_service().new_service(&cfg)).unwrap() } /// Calls service and waits for response future completion. @@ -93,7 +100,7 @@ where /// ``` pub fn call_success(app: &mut S, req: R) -> S::Response where - S: Service, Error = E>, + S: Service, Error = E>, E: std::fmt::Debug, { block_on(app.call(req)).unwrap()