stopping point

This commit is contained in:
Nikolay Kim 2022-02-09 00:22:45 +06:00
parent 13af01d5a9
commit 0886f27082
31 changed files with 1074 additions and 1002 deletions

View file

@ -151,9 +151,9 @@ impl Route {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct #name; pub struct #name;
impl ntex::web::dev::WebServiceFactory<#error> for #name impl<'a> ntex::web::WebService<'a, #error> for #name
{ {
fn register(self, __config: &mut ntex::web::dev::WebServiceConfig<#error>) { fn register(self, __config: &mut ntex::web::WebServiceConfig<'a, #error>) {
#ast #ast
let __resource = ntex::web::Resource::new(#path) let __resource = ntex::web::Resource::new(#path)
@ -162,7 +162,7 @@ impl Route {
#(.guard(ntex::web::guard::fn_guard(#extra_guards)))* #(.guard(ntex::web::guard::fn_guard(#extra_guards)))*
.to(#name); .to(#name);
ntex::web::dev::WebServiceFactory::register(__resource, __config) ntex::web::WebService::register(__resource, __config)
} }
} }
}; };

View file

@ -135,7 +135,7 @@ pub trait Service<Req> {
/// ///
/// Note that this function consumes the receiving service and returns a /// Note that this function consumes the receiving service and returns a
/// wrapped version of it. /// wrapped version of it.
fn map_err<F, E>(self, f: F) -> crate::dev::MapErr<Self, Req, F, E> fn map_err<F, E>(self, f: F) -> crate::dev::MapErr<Self, F, E>
where where
Self: Sized, Self: Sized,
F: Fn(Self::Error) -> E, F: Fn(Self::Error) -> E,
@ -185,23 +185,17 @@ pub trait ServiceFactory<Req, Cfg = ()> {
#[inline] #[inline]
/// Map this service's error to a different error, returning a new service. /// Map this service's error to a different error, returning a new service.
fn map_err<F, E>( fn map_err<F, E>(self, f: F) -> crate::map_err::MapErrServiceFactory<Self, Cfg, F, E>
self,
f: F,
) -> crate::map_err::MapErrServiceFactory<Self, Req, Cfg, F, E>
where where
Self: Sized, Self: Sized,
F: Fn(Self::Error) -> E + Clone, F: Fn(Self::Error) -> E + Clone,
{ {
crate::map_err::MapErrServiceFactory::<_, _, Cfg, _, _>::new(self, f) crate::map_err::MapErrServiceFactory::new(self, f)
} }
#[inline] #[inline]
/// Map this factory's init error to a different error, returning a new service. /// Map this factory's init error to a different error, returning a new service.
fn map_init_err<F, E>( fn map_init_err<F, E>(self, f: F) -> crate::map_init_err::MapInitErr<Self, F, E>
self,
f: F,
) -> crate::map_init_err::MapInitErr<Self, Req, Cfg, F, E>
where where
Self: Sized, Self: Sized,
F: Fn(Self::InitError) -> E + Clone, F: Fn(Self::InitError) -> E + Clone,

View file

@ -6,19 +6,15 @@ use super::{Service, ServiceFactory};
/// error. /// error.
/// ///
/// This is created by the `ServiceExt::map_err` method. /// This is created by the `ServiceExt::map_err` method.
pub struct MapErr<A, R, F, E> { pub struct MapErr<A, F, E> {
service: A, service: A,
f: F, f: F,
_t: PhantomData<fn(R) -> E>, _t: PhantomData<E>,
} }
impl<A, R, F, E> MapErr<A, R, F, E> { impl<A, F, E> MapErr<A, F, E> {
/// Create new `MapErr` combinator /// Create new `MapErr` combinator
pub(crate) fn new(service: A, f: F) -> Self pub(crate) fn new(service: A, f: F) -> Self {
where
A: Service<R>,
F: Fn(A::Error) -> E,
{
Self { Self {
service, service,
f, f,
@ -27,7 +23,7 @@ impl<A, R, F, E> MapErr<A, R, F, E> {
} }
} }
impl<A, R, F, E> Clone for MapErr<A, R, F, E> impl<A, F, E> Clone for MapErr<A, F, E>
where where
A: Clone, A: Clone,
F: Clone, F: Clone,
@ -42,7 +38,7 @@ where
} }
} }
impl<A, R, F, E> Service<R> for MapErr<A, R, F, E> impl<A, R, F, E> Service<R> for MapErr<A, F, E>
where where
A: Service<R>, A: Service<R>,
F: Fn(A::Error) -> E + Clone, F: Fn(A::Error) -> E + Clone,
@ -106,21 +102,13 @@ where
/// service's error. /// service's error.
/// ///
/// This is created by the `NewServiceExt::map_err` method. /// This is created by the `NewServiceExt::map_err` method.
pub struct MapErrServiceFactory<A, R, C, F, E> pub struct MapErrServiceFactory<A, C, F, E> {
where
A: ServiceFactory<R, C>,
F: Fn(A::Error) -> E + Clone,
{
a: A, a: A,
f: F, f: F,
e: PhantomData<fn(R, C) -> E>, e: PhantomData<(C, E)>,
} }
impl<A, R, C, F, E> MapErrServiceFactory<A, R, C, F, E> impl<A, C, F, E> MapErrServiceFactory<A, C, F, E> {
where
A: ServiceFactory<R, C>,
F: Fn(A::Error) -> E + Clone,
{
/// Create new `MapErr` new service instance /// Create new `MapErr` new service instance
pub(crate) fn new(a: A, f: F) -> Self { pub(crate) fn new(a: A, f: F) -> Self {
Self { Self {
@ -131,10 +119,10 @@ where
} }
} }
impl<A, R, C, F, E> Clone for MapErrServiceFactory<A, R, C, F, E> impl<A, C, F, E> Clone for MapErrServiceFactory<A, C, F, E>
where where
A: ServiceFactory<R, C> + Clone, A: Clone,
F: Fn(A::Error) -> E + Clone, F: Clone,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@ -145,7 +133,7 @@ where
} }
} }
impl<A, R, C, F, E> ServiceFactory<R, C> for MapErrServiceFactory<A, R, C, F, E> impl<A, R, C, F, E> ServiceFactory<R, C> for MapErrServiceFactory<A, C, F, E>
where where
A: ServiceFactory<R, C>, A: ServiceFactory<R, C>,
F: Fn(A::Error) -> E + Clone, F: Fn(A::Error) -> E + Clone,
@ -153,7 +141,7 @@ where
type Response = A::Response; type Response = A::Response;
type Error = E; type Error = E;
type Service = MapErr<A::Service, R, F, E>; type Service = MapErr<A::Service, F, E>;
type InitError = A::InitError; type InitError = A::InitError;
type Future = MapErrServiceFuture<A, R, C, F, E>; type Future = MapErrServiceFuture<A, R, C, F, E>;
@ -190,7 +178,7 @@ where
A: ServiceFactory<R, C>, A: ServiceFactory<R, C>,
F: Fn(A::Error) -> E + Clone, F: Fn(A::Error) -> E + Clone,
{ {
type Output = Result<MapErr<A::Service, R, F, E>, A::InitError>; type Output = Result<MapErr<A::Service, F, E>, A::InitError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();

View file

@ -3,17 +3,13 @@ use std::{future::Future, marker::PhantomData, pin::Pin, task::Context, task::Po
use super::ServiceFactory; use super::ServiceFactory;
/// `MapInitErr` service combinator /// `MapInitErr` service combinator
pub struct MapInitErr<A, R, C, F, E> { pub struct MapInitErr<A, F, E> {
a: A, a: A,
f: F, f: F,
e: PhantomData<fn(R, C) -> E>, e: PhantomData<E>,
} }
impl<A, R, C, F, E> MapInitErr<A, R, C, F, E> impl<A, F, E> MapInitErr<A, F, E> {
where
A: ServiceFactory<R, C>,
F: Fn(A::InitError) -> E,
{
/// Create new `MapInitErr` combinator /// Create new `MapInitErr` combinator
pub(crate) fn new(a: A, f: F) -> Self { pub(crate) fn new(a: A, f: F) -> Self {
Self { Self {
@ -24,7 +20,7 @@ where
} }
} }
impl<A, R, C, F, E> Clone for MapInitErr<A, R, C, F, E> impl<A, F, E> Clone for MapInitErr<A, F, E>
where where
A: Clone, A: Clone,
F: Clone, F: Clone,
@ -38,7 +34,7 @@ where
} }
} }
impl<A, R, C, F, E> ServiceFactory<R, C> for MapInitErr<A, R, C, F, E> impl<A, R, C, F, E> ServiceFactory<R, C> for MapInitErr<A, F, E>
where where
A: ServiceFactory<R, C>, A: ServiceFactory<R, C>,
F: Fn(A::InitError) -> E + Clone, F: Fn(A::InitError) -> E + Clone,
@ -48,7 +44,7 @@ where
type Service = A::Service; type Service = A::Service;
type InitError = E; type InitError = E;
type Future = MapInitErrFuture<A, R, C, F, E>; type Future = MapInitErrFuture<A::Future, A::Service, A::InitError, F, E>;
fn new_service(&self, cfg: C) -> Self::Future { fn new_service(&self, cfg: C) -> Self::Future {
MapInitErrFuture { MapInitErrFuture {
@ -59,23 +55,23 @@ where
} }
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
pub struct MapInitErrFuture<A, R, C, F, E> pub struct MapInitErrFuture<Fut, Srv, Err, F, E>
where where
A: ServiceFactory<R, C>, F: Fn(Err) -> E,
F: Fn(A::InitError) -> E, Fut: Future<Output = Result<Srv, Err>>,
{ {
f: F, f: F,
#[pin] #[pin]
fut: A::Future, fut: Fut,
} }
} }
impl<A, R, C, F, E> Future for MapInitErrFuture<A, R, C, F, E> impl<Fut, Srv, Err, F, E> Future for MapInitErrFuture<Fut, Srv, Err, F, E>
where where
A: ServiceFactory<R, C>, F: Fn(Err) -> E,
F: Fn(A::InitError) -> E, Fut: Future<Output = Result<Srv, Err>>,
{ {
type Output = Result<A::Service, E>; type Output = Result<Srv, E>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();

View file

@ -105,7 +105,7 @@ impl<T: Service<R>, R> Pipeline<T, R> {
/// ///
/// Note that this function consumes the receiving service and returns a /// Note that this function consumes the receiving service and returns a
/// wrapped version of it. /// wrapped version of it.
pub fn map_err<F, E>(self, f: F) -> Pipeline<MapErr<T, R, F, E>, R> pub fn map_err<F, E>(self, f: F) -> Pipeline<MapErr<T, F, E>, R>
where where
Self: Sized, Self: Sized,
F: Fn(T::Error) -> E, F: Fn(T::Error) -> E,
@ -228,7 +228,7 @@ impl<T: ServiceFactory<R, C>, R, C> PipelineFactory<T, R, C> {
pub fn map_err<F, E>( pub fn map_err<F, E>(
self, self,
f: F, f: F,
) -> PipelineFactory<MapErrServiceFactory<T, R, C, F, E>, R, C> ) -> PipelineFactory<MapErrServiceFactory<T, C, F, E>, R, C>
where where
Self: Sized, Self: Sized,
F: Fn(T::Error) -> E + Clone, F: Fn(T::Error) -> E + Clone,
@ -240,10 +240,7 @@ impl<T: ServiceFactory<R, C>, R, C> PipelineFactory<T, R, C> {
} }
/// Map this factory's init error to a different error, returning a new service. /// Map this factory's init error to a different error, returning a new service.
pub fn map_init_err<F, E>( pub fn map_init_err<F, E>(self, f: F) -> PipelineFactory<MapInitErr<T, F, E>, R, C>
self,
f: F,
) -> PipelineFactory<MapInitErr<T, R, C, F, E>, R, C>
where where
Self: Sized, Self: Sized,
F: Fn(T::InitError) -> E + Clone, F: Fn(T::InitError) -> E + Clone,

42
ntex/examples/basic.rs Normal file
View file

@ -0,0 +1,42 @@
use ntex::http;
use ntex::web::{self, middleware, App, HttpRequest, HttpResponse, HttpServer};
#[web::get("/resource1/{name}/index.html")]
async fn index(req: HttpRequest, name: web::types::Path<String>) -> String {
println!("REQ: {:?}", req);
format!("Hello: {}!\r\n", name)
}
async fn index_async(req: HttpRequest) -> &'static str {
println!("REQ: {:?}", req);
"Hello world!\r\n"
}
#[web::get("/")]
async fn no_params() -> &'static str {
"Hello world!\r\n"
}
#[ntex::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "ntex=trace");
env_logger::init();
HttpServer::new(|| {
App::new()
.wrap(middleware::Logger::default())
.service((index, no_params))
.service(
web::resource("/resource2/index.html")
.wrap(middleware::DefaultHeaders::new().header("X-Version-R2", "0.3"))
.default(|| async { HttpResponse::MethodNotAllowed() })
.route(web::get().to(index_async)),
)
.service(web::resource("/test1.html").to(|| async { "Test\r\n" }))
})
.bind("0.0.0.0:8081")?
.workers(4)
.keep_alive(http::KeepAlive::Disabled)
.run()
.await
}

25
ntex/examples/client.rs Normal file
View file

@ -0,0 +1,25 @@
use ntex::http::client::{error::SendRequestError, Client};
#[ntex::main]
async fn main() -> Result<(), SendRequestError> {
std::env::set_var("RUST_LOG", "ntex=trace");
env_logger::init();
let client = Client::new();
// Create request builder, configure request and send
let mut response = client
.get("https://www.rust-lang.org/")
.header("User-Agent", "ntex")
.send()
.await?;
// server http response
println!("Response: {:?}", response);
// read response body
let body = response.body().await.unwrap();
println!("Downloaded: {:?} bytes", body.len());
Ok(())
}

35
ntex/examples/echo.rs Normal file
View file

@ -0,0 +1,35 @@
use std::{env, io};
use futures_util::StreamExt;
use log::info;
use ntex::http::header::HeaderValue;
use ntex::http::{HttpService, Request, Response};
use ntex::{server::Server, time::Seconds, util::BytesMut};
#[ntex::main]
async fn main() -> io::Result<()> {
env::set_var("RUST_LOG", "echo=info");
env_logger::init();
Server::build()
.bind("echo", "127.0.0.1:8080", |_| {
HttpService::build()
.client_timeout(Seconds(1))
.disconnect_timeout(Seconds(1))
.finish(|mut req: Request| async move {
let mut body = BytesMut::new();
while let Some(item) = req.payload().next().await {
body.extend_from_slice(&item.unwrap());
}
info!("request body: {:?}", body);
Ok::<_, io::Error>(
Response::Ok()
.header("x-head", HeaderValue::from_static("dummy value!"))
.body(body),
)
})
})?
.run()
.await
}

31
ntex/examples/echo2.rs Normal file
View file

@ -0,0 +1,31 @@
use std::{env, io};
use futures_util::StreamExt;
use log::info;
use ntex::http::{header::HeaderValue, HttpService, Request, Response};
use ntex::{server::Server, util::BytesMut};
async fn handle_request(mut req: Request) -> Result<Response, io::Error> {
let mut body = BytesMut::new();
while let Some(item) = req.payload().next().await {
body.extend_from_slice(&item.unwrap())
}
info!("request body: {:?}", body);
Ok(Response::Ok()
.header("x-head", HeaderValue::from_static("dummy value!"))
.body(body))
}
#[ntex::main]
async fn main() -> io::Result<()> {
env::set_var("RUST_LOG", "echo=info");
env_logger::init();
Server::build()
.bind("echo", "127.0.0.1:8080", |_| {
HttpService::build().finish(handle_request)
})?
.run()
.await
}

View file

@ -0,0 +1,27 @@
use std::{env, io};
use log::info;
use ntex::http::header::HeaderValue;
use ntex::http::{HttpService, Response};
use ntex::{server::Server, time::Seconds, util::Ready};
#[ntex::main]
async fn main() -> io::Result<()> {
env::set_var("RUST_LOG", "ntex=trace,hello_world=info");
env_logger::init();
Server::build()
.bind("hello-world", "127.0.0.1:8080", |_| {
HttpService::build()
.client_timeout(Seconds(1))
.disconnect_timeout(Seconds(1))
.finish(|_req| {
info!("{:?}", _req);
let mut res = Response::Ok();
res.header("x-head", HeaderValue::from_static("dummy value!"));
Ready::Ok::<_, io::Error>(res.body("Hello world!"))
})
})?
.run()
.await
}

47
ntex/examples/uds.rs Normal file
View file

@ -0,0 +1,47 @@
use ntex::web::{self, middleware, App, HttpRequest, HttpResponse, HttpServer};
#[web::get("/resource1/{name}/index.html")]
async fn index(req: HttpRequest, name: web::types::Path<String>) -> String {
println!("REQ: {:?}", req);
format!("Hello: {}!\r\n", name)
}
async fn index_async(req: HttpRequest) -> Result<&'static str, std::io::Error> {
println!("REQ: {:?}", req);
Ok("Hello world!\r\n")
}
#[web::get("/")]
async fn no_params() -> &'static str {
"Hello world!\r\n"
}
#[cfg(unix)]
#[ntex::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "ntex=info");
env_logger::init();
HttpServer::new(|| {
App::new()
.wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.wrap(middleware::Logger::default())
.service((index, no_params))
.service(
web::resource("/resource2/index.html")
.wrap(middleware::DefaultHeaders::new().header("X-Version-R2", "0.3"))
.default_service(
web::route().to(|| async { HttpResponse::MethodNotAllowed() }),
)
.route(web::get().to(index_async)),
)
.service(web::resource("/test1.html").to(|| async { "Test\r\n" }))
})
.bind_uds("/tmp/uds-test")?
.workers(1)
.run()
.await
}
#[cfg(not(unix))]
fn main() {}

View file

@ -28,6 +28,8 @@ pub trait ResponseError: fmt::Display + fmt::Debug {
} }
} }
impl ResponseError for std::convert::Infallible {}
impl<'a, T: ResponseError> ResponseError for &'a T { impl<'a, T: ResponseError> ResponseError for &'a T {
fn error_response(&self) -> Response { fn error_response(&self) -> Response {
(*self).error_response() (*self).error_response()

View file

@ -6,11 +6,13 @@ use crate::service::{map_config, pipeline_factory, PipelineFactory};
use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Transform}; use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Transform};
use crate::util::Extensions; use crate::util::Extensions;
use super::app_service::{AppFactory, AppService}; use super::app_service::{
AppFactory, AppFactoryInner, AppRouting, AppService, DefaultService,
};
use super::boxed::{self, BoxServiceFactory}; use super::boxed::{self, BoxServiceFactory};
use super::config::{AppConfig, ServiceConfig}; use super::config::{AppConfig, ServiceConfig};
use super::service::{AppServiceFactory, ServiceFactoryWrapper, WebServiceFactory}; use super::service::{create_web_service, WebService, WebServiceWrapper};
use super::stack::{Filter, Next, Stack}; use super::stack::{Filter, Filters, FiltersFactory, Next, Stack};
use super::types::state::{State, StateFactory}; use super::types::state::{State, StateFactory};
use super::{DefaultError, ErrorRenderer, Resource, Route, WebRequest, WebResponse}; use super::{DefaultError, ErrorRenderer, Resource, Route, WebRequest, WebResponse};
@ -21,9 +23,9 @@ type FnStateFactory =
/// for building application instances. /// for building application instances.
pub struct App<'a, M, F, Err: ErrorRenderer = DefaultError> { pub struct App<'a, M, F, Err: ErrorRenderer = DefaultError> {
middleware: M, middleware: M,
filter: PipelineFactory<F, &'a mut WebRequest<Err>>, filter: F,
services: Vec<Box<dyn AppServiceFactory<'a, Err>>>, services: Vec<Box<dyn WebServiceWrapper<'a, Err>>>,
default: Option<Rc<BoxServiceFactory<'a, Err>>>, default: BoxServiceFactory<'a, Err>,
state: Vec<Box<dyn StateFactory>>, state: Vec<Box<dyn StateFactory>>,
state_factories: Vec<FnStateFactory>, state_factories: Vec<FnStateFactory>,
external: Vec<ResourceDef>, external: Vec<ResourceDef>,
@ -32,53 +34,44 @@ pub struct App<'a, M, F, Err: ErrorRenderer = DefaultError> {
case_insensitive: bool, case_insensitive: bool,
} }
impl<'a> App<'a, Identity, Filter<DefaultError>, DefaultError> { impl<'a> App<'a, Identity, Filter, DefaultError> {
/// Create application builder. Application can be configured with a builder-like pattern. /// Create application builder. Application can be configured with a builder-like pattern.
pub fn new() -> Self { pub fn new() -> Self {
// App { App {
// middleware: Identity, filter: Filter,
// filter: pipeline_factory(Filter::new()), middleware: Identity,
// state: Vec::new(), state: Vec::new(),
// state_factories: Vec::new(), state_factories: Vec::new(),
// services: Vec::new(), services: Vec::new(),
// default: None, default: boxed::factory(DefaultService::default()),
// external: Vec::new(), external: Vec::new(),
// extensions: Extensions::new(), extensions: Extensions::new(),
// error_renderer: DefaultError, error_renderer: DefaultError,
// case_insensitive: false, case_insensitive: false,
// } }
todo!()
} }
} }
impl<'a, Err: ErrorRenderer> App<'a, Identity, Filter<Err>, Err> { impl<'a, Err: ErrorRenderer> App<'a, Identity, Filter, Err> {
/// Create application builder with custom error renderer. /// Create application builder with custom error renderer.
pub fn with(err: Err) -> Self { pub fn with(err: Err) -> Self {
// App { App {
// middleware: Identity, filter: Filter,
// filter: pipeline_factory(Filter::new()), middleware: Identity,
// state: Vec::new(), state: Vec::new(),
// state_factories: Vec::new(), state_factories: Vec::new(),
// services: Vec::new(), services: Vec::new(),
// default: None, default: boxed::factory(DefaultService::default()),
// external: Vec::new(), external: Vec::new(),
// extensions: Extensions::new(), extensions: Extensions::new(),
// error_renderer: err, error_renderer: err,
// case_insensitive: false, case_insensitive: false,
// } }
todo!()
} }
} }
impl<'a, M, T, Err> App<'a, M, T, Err> impl<'a, M, F, Err> App<'a, M, F, Err>
where where
T: ServiceFactory<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
Error = Err::Container,
InitError = (),
>,
T::Future: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
/// Set application state. Application state could be accessed /// Set application state. Application state could be accessed
@ -119,9 +112,9 @@ where
/// Set application state factory. This function is /// Set application state factory. This function is
/// similar to `.state()` but it accepts state factory. State object get /// similar to `.state()` but it accepts state factory. State object get
/// constructed asynchronously during application initialization. /// constructed asynchronously during application initialization.
pub fn state_factory<F, Out, D, E>(mut self, state: F) -> Self pub fn state_factory<T, Out, D, E>(mut self, state: T) -> Self
where where
F: Fn() -> Out + 'static, T: Fn() -> Out + 'static,
Out: Future<Output = Result<D, E>> + 'static, Out: Future<Output = Result<D, E>> + 'static,
D: 'static, D: 'static,
E: fmt::Debug, E: fmt::Debug,
@ -181,9 +174,9 @@ where
/// .route("/index.html", web::get().to(|| async { HttpResponse::Ok() })); /// .route("/index.html", web::get().to(|| async { HttpResponse::Ok() }));
/// } /// }
/// ``` /// ```
pub fn configure<F>(mut self, f: F) -> Self pub fn configure<U>(mut self, f: U) -> Self
where where
F: FnOnce(&mut ServiceConfig<'a, Err>), U: FnOnce(&mut ServiceConfig<'a, Err>),
{ {
let mut cfg = ServiceConfig::new(); let mut cfg = ServiceConfig::new();
f(&mut cfg); f(&mut cfg);
@ -213,12 +206,11 @@ where
/// } /// }
/// ``` /// ```
pub fn route(self, path: &str, mut route: Route<Err>) -> Self { pub fn route(self, path: &str, mut route: Route<Err>) -> Self {
// self.service( self.service(
// Resource::new(path) Resource::new(path)
// .add_guards(route.take_guards()) .add_guards(route.take_guards())
// .route(route), .route(route),
// ) )
self
} }
/// Register http service. /// Register http service.
@ -230,12 +222,11 @@ where
/// * *Resource* is an entry in resource table which corresponds to requested URL. /// * *Resource* is an entry in resource table which corresponds to requested URL.
/// * *Scope* is a set of resources with common root path. /// * *Scope* is a set of resources with common root path.
/// * "StaticFiles" is a service for static files support /// * "StaticFiles" is a service for static files support
pub fn service<F>(mut self, factory: F) -> Self pub fn service<U>(mut self, factory: U) -> Self
where where
F: WebServiceFactory<'a, Err> + 'static, U: WebService<'a, Err> + 'static,
{ {
self.services self.services.push(create_web_service(factory));
.push(Box::new(ServiceFactoryWrapper::new(factory)));
self self
} }
@ -268,25 +259,28 @@ where
/// let app = App::new() /// let app = App::new()
/// .service( /// .service(
/// web::resource("/index.html").to(|| async { HttpResponse::Ok() })) /// web::resource("/index.html").to(|| async { HttpResponse::Ok() }))
/// .default_service( /// .default(
/// web::to(|| async { HttpResponse::NotFound() }) /// web::to(|| async { HttpResponse::NotFound() })
/// ); /// );
/// } /// }
/// ``` /// ```
pub fn default_service<F, U>(mut self, f: F) -> Self pub fn default<T, U>(mut self, f: T) -> Self
where where
F: IntoServiceFactory<U, &'a mut WebRequest<Err>>, T: IntoServiceFactory<U, &'a mut WebRequest<'a, Err>>,
U: ServiceFactory< U: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
> + 'static, > + 'static,
U::InitError: fmt::Debug, U::Service: 'static,
U::Future: 'static,
U::InitError: fmt::Debug + 'static,
{ {
// // create and configure default resource // create and configure default resource
// self.default = Some(Rc::new(boxed::factory(f.into_factory().map_init_err( self.default =
// |e| log::error!("Cannot construct default service: {:?}", e), boxed::factory::<'a, _, _>(f.into_factory().map_init_err(|e| {
// )))); log::error!("Cannot construct default service: {:?}", e)
}));
self self
} }
@ -349,31 +343,9 @@ where
/// .route("/index.html", web::get().to(index)); /// .route("/index.html", web::get().to(index));
/// } /// }
/// ``` /// ```
pub fn filter<S, U>( pub fn filter<U>(self, filter: U) -> App<'a, M, Filters<F, U>, Err> {
self,
filter: U,
) -> App<
'a,
M,
impl ServiceFactory<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
Error = Err::Container,
InitError = (),
>,
Err,
>
where
S: ServiceFactory<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
Error = Err::Container,
InitError = (),
>,
U: IntoServiceFactory<S, &'a mut WebRequest<Err>>,
{
App { App {
filter: self.filter.and_then(filter.into_factory()), filter: Filters::new(self.filter, filter),
middleware: self.middleware, middleware: self.middleware,
state: self.state, state: self.state,
state_factories: self.state_factories, state_factories: self.state_factories,
@ -412,7 +384,7 @@ where
/// .route("/index.html", web::get().to(index)); /// .route("/index.html", web::get().to(index));
/// } /// }
/// ``` /// ```
pub fn wrap<U>(self, mw: U) -> App<'a, Stack<M, U, Err>, T, Err> { pub fn wrap<U>(self, mw: U) -> App<'a, Stack<M, U>, F, Err> {
App { App {
middleware: Stack::new(self.middleware, mw), middleware: Stack::new(self.middleware, mw),
filter: self.filter, filter: self.filter,
@ -438,15 +410,18 @@ where
impl<'a, M, F, Err> App<'a, M, F, Err> impl<'a, M, F, Err> App<'a, M, F, Err>
where where
M: Transform<Next<AppService<'a, F::Service, Err>, Err>> + 'static, M: Transform<
M::Service: AppRouting<
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, 'a,
F: ServiceFactory< <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
&'a mut WebRequest<Err>, Err,
Response = &'a mut WebRequest<Err>, >,
Error = Err::Container,
InitError = (),
> + 'static, > + 'static,
M::Service:
Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: FiltersFactory<'a, Err> + 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
/// Construct service factory with default `AppConfig`, suitable for `http::HttpService`. /// Construct service factory with default `AppConfig`, suitable for `http::HttpService`.
@ -469,13 +444,9 @@ where
/// ``` /// ```
pub fn finish( pub fn finish(
self, self,
) -> impl ServiceFactory< ) -> impl ServiceFactory<Request, Response = WebResponse, Error = Infallible, InitError = ()>
Request, {
Response = WebResponse, IntoServiceFactory::<AppFactory, Request, ()>::into_factory(self)
Error = Err::Container,
InitError = (),
> + 'a {
IntoServiceFactory::<AppFactory<'a, M, F, Err>, Request, ()>::into_factory(self)
} }
/// Construct service factory suitable for `http::HttpService`. /// Construct service factory suitable for `http::HttpService`.
@ -499,82 +470,85 @@ where
pub fn with_config( pub fn with_config(
self, self,
cfg: AppConfig, cfg: AppConfig,
) -> impl ServiceFactory< ) -> impl ServiceFactory<Request, Response = WebResponse, Error = Infallible, InitError = ()>
Request, {
Response = WebResponse, let app = AppFactoryInner {
Error = Err::Container, filter: Some(self.filter),
InitError = (),
> + 'a {
let app = AppFactory {
filter: self.filter,
middleware: Rc::new(self.middleware), middleware: Rc::new(self.middleware),
state: Rc::new(self.state), state: Rc::new(self.state),
state_factories: Rc::new(self.state_factories), state_factories: Rc::new(self.state_factories),
services: Rc::new(RefCell::new(self.services)), services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external), external: RefCell::new(self.external),
default: self.default, default: Some(self.default),
extensions: RefCell::new(Some(self.extensions)), extensions: RefCell::new(Some(self.extensions)),
case_insensitive: self.case_insensitive, case_insensitive: self.case_insensitive,
}; };
map_config(app, move |_| cfg.clone()) map_config(AppFactory::new(app), move |_| cfg.clone())
} }
} }
impl<'a, M, F, Err> IntoServiceFactory<AppFactory<'a, M, F, Err>, Request, AppConfig> impl<'a, M, F, Err> IntoServiceFactory<AppFactory, Request, AppConfig>
for App<'a, M, F, Err> for App<'a, M, F, Err>
where where
M: Transform<Next<AppService<'a, F::Service, Err>, Err>> + 'static, M: 'static,
M: Transform<
AppRouting<
'a,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err,
>,
>,
M::Service: M::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: ServiceFactory< F: FiltersFactory<'a, Err> + 'static,
&'a mut WebRequest<Err>, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
Response = &'a mut WebRequest<Err>, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Error = Err::Container,
InitError = (),
> + 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
fn into_factory(self) -> AppFactory<'a, M, F, Err> { fn into_factory(self) -> AppFactory {
AppFactory { AppFactory::new(AppFactoryInner {
filter: self.filter, filter: Some(self.filter),
middleware: Rc::new(self.middleware), middleware: Rc::new(self.middleware),
state: Rc::new(self.state), state: Rc::new(self.state),
state_factories: Rc::new(self.state_factories), state_factories: Rc::new(self.state_factories),
services: Rc::new(RefCell::new(self.services)), services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external), external: RefCell::new(self.external),
default: self.default, default: Some(self.default),
extensions: RefCell::new(Some(self.extensions)), extensions: RefCell::new(Some(self.extensions)),
case_insensitive: self.case_insensitive, case_insensitive: self.case_insensitive,
} })
} }
} }
impl<'a, M, F, Err> IntoServiceFactory<AppFactory<'a, M, F, Err>, Request, ()> impl<'a, M, F, Err> IntoServiceFactory<AppFactory, Request, ()> for App<'a, M, F, Err>
for App<'a, M, F, Err>
where where
M: Transform<Next<AppService<'a, F::Service, Err>, Err>> + 'static, M: 'static,
M: Transform<
AppRouting<
'a,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err,
>,
>,
M::Service: M::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: ServiceFactory< F: FiltersFactory<'a, Err> + 'static,
&'a mut WebRequest<Err>, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
Response = &'a mut WebRequest<Err>, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Error = Err::Container,
InitError = (),
> + 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
fn into_factory(self) -> AppFactory<'a, M, F, Err> { fn into_factory(self) -> AppFactory {
AppFactory { AppFactory::new(AppFactoryInner {
filter: self.filter, filter: Some(self.filter),
middleware: Rc::new(self.middleware), middleware: Rc::new(self.middleware),
state: Rc::new(self.state), state: Rc::new(self.state),
state_factories: Rc::new(self.state_factories), state_factories: Rc::new(self.state_factories),
services: Rc::new(RefCell::new(self.services)), services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external), external: RefCell::new(self.external),
default: self.default, default: Some(self.default),
extensions: RefCell::new(Some(self.extensions)), extensions: RefCell::new(Some(self.extensions)),
case_insensitive: self.case_insensitive, case_insensitive: self.case_insensitive,
} })
} }
} }
@ -611,12 +585,10 @@ mod tests {
.service(web::resource("/test").to(|| async { HttpResponse::Ok() })) .service(web::resource("/test").to(|| async { HttpResponse::Ok() }))
.service( .service(
web::resource("/test2") web::resource("/test2")
.default_service(|r: WebRequest<DefaultError>| async move { .default(|| async move { HttpResponse::Created() })
Ok(r.into_response(HttpResponse::Created()))
})
.route(web::get().to(|| async { HttpResponse::Ok() })), .route(web::get().to(|| async { HttpResponse::Ok() })),
) )
.default_service(|r: WebRequest<DefaultError>| async move { .default(|r: WebRequest<'_, DefaultError>| async move {
Ok(r.into_response(HttpResponse::MethodNotAllowed())) Ok(r.into_response(HttpResponse::MethodNotAllowed()))
}) })
.with_config(Default::default()) .with_config(Default::default())

View file

@ -7,106 +7,198 @@ use crate::router::{Path, ResourceDef, Router};
use crate::service::{ use crate::service::{
fn_service, into_service, PipelineFactory, Service, ServiceFactory, Transform, fn_service, into_service, PipelineFactory, Service, ServiceFactory, Transform,
}; };
use crate::util::{ready, Extensions}; use crate::util::{ready, Extensions, Ready};
use super::boxed::{self, BoxService, BoxServiceFactory}; use super::boxed::{self, BoxService, BoxServiceFactory};
use super::config::AppConfig; use super::config::AppConfig;
use super::guard::Guard; use super::guard::Guard;
use super::httprequest::{HttpRequest, HttpRequestPool}; use super::httprequest::{HttpRequest, HttpRequestPool};
use super::rmap::ResourceMap; use super::rmap::ResourceMap;
use super::service::{AppServiceFactory, WebServiceConfig}; use super::service::{WebService, WebServiceConfig, WebServiceWrapper};
use super::stack::Next; use super::stack::{Filter, FiltersFactory, Next};
use super::types::state::StateFactory; use super::types::state::StateFactory;
use super::{ErrorRenderer, WebRequest, WebResponse}; use super::{ErrorContainer, ErrorRenderer, WebRequest, WebResponse};
type Guards = Vec<Box<dyn Guard>>; type Guards = Vec<Box<dyn Guard>>;
type BoxResponse<'a, Err: ErrorRenderer> = type BoxResponse<'a> = Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>> + 'a>>;
Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'a>>;
type FnStateFactory = type FnStateFactory =
Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<Box<dyn StateFactory>, ()>>>>>; Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<Box<dyn StateFactory>, ()>>>>>;
/// Service factory to convert `Request` to a `WebRequest<S>`. /// Service factory for converting `Request` to a `WebResponse>`.
///
/// It also executes state factories. /// It also executes state factories.
pub struct AppFactory<'a, T, F, Err: ErrorRenderer> pub struct AppFactory(WebAppFactory);
where
F: ServiceFactory< pub struct AppService(WebAppHandler);
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>, type WebAppFactory =
Error = Err::Container, Box<dyn Fn(AppConfig) -> Pin<Box<dyn Future<Output = Result<AppService, ()>>>>>;
InitError = (), type WebAppHandler =
> + 'static, Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>>>>>;
Err: ErrorRenderer, type WebAppHandler2<'a> = Box<
{ dyn Fn(Request) -> Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>> + 'a>>
pub(super) middleware: Rc<T>, + 'a,
pub(super) filter: PipelineFactory<F, &'a mut WebRequest<Err>>, >;
pub(super) extensions: RefCell<Option<Extensions>>,
pub(super) state: Rc<Vec<Box<dyn StateFactory>>>, impl AppFactory {
pub(super) state_factories: Rc<Vec<FnStateFactory>>, pub(super) fn new<'a, M, F, Err: ErrorRenderer>(
pub(super) services: Rc<RefCell<Vec<Box<dyn AppServiceFactory<'a, Err>>>>>, app: AppFactoryInner<'a, M, F, Err>,
pub(super) default: Option<Rc<BoxServiceFactory<'a, Err>>>, ) -> Self
pub(super) external: RefCell<Vec<ResourceDef>>, where
pub(super) case_insensitive: bool, M: Transform<
AppRouting<
'a,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err,
>,
> + 'static,
M::Service: Service<
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Infallible,
>,
F: FiltersFactory<'a, Err> + 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Err: ErrorRenderer,
{
let app = RefCell::new(app);
let b: Box<
dyn Fn(AppConfig) -> Pin<Box<dyn Future<Output = Result<AppService, ()>>>> + 'a,
> = Box::new(move |cfg| {
let fut = app.borrow_mut().create(cfg);
Box::pin(async move { Ok(AppService(fut.await?)) })
});
AppFactory(unsafe { std::mem::transmute(b) })
}
} }
impl<'a, T, F, Err> ServiceFactory<Request> for AppFactory<'a, T, F, Err> impl ServiceFactory<Request> for AppFactory {
where
T: Transform<Next<AppService<'a, F::Service, Err>, Err>> + 'static,
T::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
F: ServiceFactory<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
Error = Err::Container,
InitError = (),
> + 'static,
Err: ErrorRenderer,
{
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Infallible;
type InitError = (); type InitError = ();
type Service = AppFactoryService<'a, T::Service, Err>; type Service = AppService;
type Future = type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>> + 'a>>;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
ServiceFactory::<Request, AppConfig>::new_service(self, AppConfig::default()) ServiceFactory::<Request, AppConfig>::new_service(self, AppConfig::default())
} }
} }
impl<'a, T, F, Err> ServiceFactory<Request, AppConfig> for AppFactory<'a, T, F, Err> impl ServiceFactory<Request, AppConfig> for AppFactory {
type Response = WebResponse;
type Error = Infallible;
type InitError = ();
type Service = AppService;
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
fn new_service(&self, cfg: AppConfig) -> Self::Future {
(&*self.0)(cfg)
}
}
impl Service<Request> for AppService {
type Response = WebResponse;
type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&self, req: Request) -> Self::Future {
(&*self.0)(req)
}
}
/// Service factory to convert `Request` to a `WebRequest<S>`.
/// It also executes state factories.
pub(super) struct AppFactoryInner<'a, M, F, Err: ErrorRenderer>
where where
T: Transform<Next<AppService<'a, F::Service, Err>, Err>> + 'static, M: Transform<
T::Service: AppRouting<
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, 'a,
F: ServiceFactory< <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
&'a mut WebRequest<Err>, Err,
Response = &'a mut WebRequest<Err>, >,
Error = Err::Container, >,
InitError = (), M::Service:
> + 'static, Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: FiltersFactory<'a, Err>,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
{
pub(super) middleware: Rc<M>,
pub(super) filter: Option<F>,
pub(super) extensions: RefCell<Option<Extensions>>,
pub(super) state: Rc<Vec<Box<dyn StateFactory>>>,
pub(super) state_factories: Rc<Vec<FnStateFactory>>,
pub(super) services: Rc<RefCell<Vec<Box<dyn WebServiceWrapper<'a, Err>>>>>,
pub(super) default: Option<BoxServiceFactory<'a, Err>>,
pub(super) external: RefCell<Vec<ResourceDef>>,
pub(super) case_insensitive: bool,
}
#[derive(Copy, Clone)]
pub(super) struct DefaultService<Err>(PhantomData<Err>);
impl<Err> Default for DefaultService<Err> {
fn default() -> Self {
DefaultService(PhantomData)
}
}
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>>
for DefaultService<Err>
{ {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type InitError = (); type InitError = ();
type Service = AppFactoryService<'a, T::Service, Err>; type Service = Self;
type Future = type Future = Ready<Self::Service, Self::InitError>;
Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>> + 'a>>;
fn new_service(&self, config: AppConfig) -> Self::Future { fn new_service(&self, cfg: ()) -> Self::Future {
Ready::Ok(DefaultService(PhantomData))
}
}
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for DefaultService<Err> {
type Response = WebResponse;
type Error = Err::Container;
type Future = Ready<Self::Response, Self::Error>;
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&self, _: &'a mut WebRequest<'a, Err>) -> Self::Future {
Ready::Ok(Response::NotFound().finish().into())
}
}
impl<'a, T, F, Err> AppFactoryInner<'a, T, F, Err>
where
T: Transform<
AppRouting<
'a,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err,
>,
> + 'static,
T::Service:
Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: FiltersFactory<'a, Err> + 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Err: ErrorRenderer + 'static,
{
pub(super) fn create(
&mut self,
config: AppConfig,
) -> Pin<Box<dyn Future<Output = Result<WebAppHandler, ()>>>> {
// update resource default service // update resource default service
let default = self.default.clone().unwrap_or_else(|| panic!()); let default = Rc::new(self.default.take().unwrap());
// .unwrap_or_else(|| {
// Rc::new(boxed::factory(into_service(
// |req: &'a mut WebRequest<Err>| {
// let res = req.into_response(Response::NotFound().finish());
// async move {
// Ok(res)
// }
// }
// )))
// });
// App config // App config
let mut config = WebServiceConfig::new(config, default.clone(), self.state.clone()); let mut config = WebServiceConfig::new(config, default.clone(), self.state.clone());
@ -142,7 +234,7 @@ where
let rmap = Rc::new(rmap); let rmap = Rc::new(rmap);
rmap.finish(rmap.clone()); rmap.finish(rmap.clone());
let filter_fut = self.filter.new_service(()); let filter_fut = self.filter.take().unwrap().create().new_service(());
let state = self.state.clone(); let state = self.state.clone();
let state_factories = self.state_factories.clone(); let state_factories = self.state_factories.clone();
let mut extensions = self let mut extensions = self
@ -152,251 +244,150 @@ where
.unwrap_or_else(Extensions::new); .unwrap_or_else(Extensions::new);
let middleware = self.middleware.clone(); let middleware = self.middleware.clone();
Box::pin(async move { let f: Pin<Box<dyn Future<Output = Result<WebAppHandler, ()>> + 'a>> =
// create http services Box::pin(async move {
for (path, factory, guards) in &mut services.iter() { // create http services
let service = factory.new_service(()).await?; for (path, factory, guards) in &mut services.iter() {
router.rdef(path.clone(), service).2 = guards.borrow_mut().take(); let service = factory.new_service(()).await?;
} router.rdef(path.clone(), service).2 = guards.borrow_mut().take();
}
let routing = AppRouting { // router
router: router.finish(), let routing = AppRouting {
default: Some(default_fut.await?), filter: filter_fut.await?,
}; router: Rc::new(AppRouter {
router: router.finish(),
default: Some(default_fut.await?),
}),
};
// main service // create app state container
let service = AppService { for f in state.iter() {
filter: filter_fut.await?,
routing: Rc::new(routing),
};
// create app state container
for f in state.iter() {
f.create(&mut extensions);
}
// async state factories
for fut in state_factories.iter() {
if let Ok(f) = fut().await {
f.create(&mut extensions); f.create(&mut extensions);
} }
}
Ok(AppFactoryService { // async state factories
rmap, for fut in state_factories.iter() {
config, if let Ok(f) = fut().await {
service: middleware.new_transform(Next::new(service)), f.create(&mut extensions);
state: Rc::new(extensions), }
pool: HttpRequestPool::create(), }
_t: PhantomData,
}) let service = middleware.new_transform(routing);
}) let state = Rc::new(extensions);
let pool = HttpRequestPool::create();
let hnd: WebAppHandler2<'a> = Box::new(move |req: Request| {
let (head, payload) = req.into_parts();
let mut req = if let Some(mut req) = pool.get_request() {
let inner = Rc::get_mut(&mut req.0).unwrap();
inner.path.set(head.uri.clone());
inner.head = head;
inner.payload = payload;
inner.app_state = state.clone();
req
} else {
HttpRequest::new(
Path::new(head.uri.clone()),
head,
payload,
rmap.clone(),
config.clone(),
state.clone(),
pool,
)
};
let mut wreq =
WebRequest::<Err>::new(unsafe { std::mem::transmute(&mut req) });
let fut = service.call(unsafe { std::mem::transmute(&mut wreq) });
Box::pin(async move {
let mut res = fut.await.unwrap();
let head = req.head();
if head.upgrade() {
res.response.head_mut().set_io(head);
}
drop(wreq);
drop(req);
Ok(res)
})
});
Ok(unsafe { std::mem::transmute(hnd) })
});
unsafe { std::mem::transmute(f) }
} }
} }
/// Service to convert `Request` to a `WebRequest<Err>` pub struct AppRouting<'a, F, Err: ErrorRenderer> {
pub struct AppFactoryService<'a, T, Err> filter: F,
where router: Rc<AppRouter<'a, Err>>,
T: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer,
{
service: T,
rmap: Rc<ResourceMap>,
config: AppConfig,
state: Rc<Extensions>,
pool: &'static HttpRequestPool,
_t: PhantomData<&'a Err>,
} }
impl<'a, T, Err> Service<Request> for AppFactoryService<'a, T, Err> struct AppRouter<'a, Err: ErrorRenderer> {
where
T: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer,
{
type Response = WebResponse;
type Error = Err::Container;
type Future = AppFactoryServiceResponse<'a, T, Err>;
#[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let _ = ready!(self.service.poll_ready(cx));
Poll::Ready(Ok(()))
}
#[inline]
fn poll_shutdown(&self, cx: &mut Context<'_>, is_error: bool) -> Poll<()> {
self.service.poll_shutdown(cx, is_error)
}
fn call(&self, req: Request) -> Self::Future {
let (head, payload) = req.into_parts();
let req = if let Some(mut req) = self.pool.get_request() {
let inner = Rc::get_mut(&mut req.0).unwrap();
inner.path.set(head.uri.clone());
inner.head = head;
inner.payload = payload;
inner.app_state = self.state.clone();
req
} else {
HttpRequest::new(
Path::new(head.uri.clone()),
head,
payload,
self.rmap.clone(),
self.config.clone(),
self.state.clone(),
self.pool,
)
};
let mut req = WebRequest::new(req);
let fut = self.service.call(&mut req);
AppFactoryServiceResponse { fut, req }
}
}
impl<'a, T, Err> Drop for AppFactoryService<'a, T, Err>
where
T: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer,
{
fn drop(&mut self) {
self.pool.clear();
}
}
pin_project_lite::pin_project! {
pub struct AppFactoryServiceResponse<'a, T: Service<&'a mut WebRequest<Err>>, Err>{
#[pin]
fut: T::Future,
req: WebRequest<Err>,
}
}
impl<'a, T, Err> Future for AppFactoryServiceResponse<'a, T, Err>
where
T: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer,
{
type Output = Result<WebResponse, Err::Container>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(Ok(ready!(self.project().fut.poll(cx)).unwrap()))
}
}
struct AppRouting<'a, Err: ErrorRenderer> {
router: Router<BoxService<'a, Err>, Guards>, router: Router<BoxService<'a, Err>, Guards>,
default: Option<BoxService<'a, Err>>, default: Option<BoxService<'a, Err>>,
} }
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for AppRouting<'a, Err> { impl<'a, F, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>>
type Response = WebResponse; for AppRouting<'a, F, Err>
type Error = Err::Container;
type Future = BoxResponse<'a, Err>;
#[inline]
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&self, mut req: &'a mut WebRequest<Err>) -> Self::Future {
let res = self.router.recognize_checked(req, |req, guards| {
if let Some(guards) = guards {
for f in guards {
if !f.check(req.head()) {
return false;
}
}
}
true
});
if let Some((srv, _info)) = res {
srv.call(req)
} else if let Some(ref default) = self.default {
default.call(req)
} else {
let req = req.into_parts().0;
Box::pin(async { Ok(WebResponse::new(Response::NotFound().finish())) })
}
}
}
/// Web app service
pub struct AppService<'a, F, Err: ErrorRenderer> {
filter: F,
routing: Rc<AppRouting<'a, Err>>,
}
impl<'a, F, Err> Service<&'a mut WebRequest<Err>> for AppService<'a, F, Err>
where where
F: Service< F: Service<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
>, >,
F::Future: 'a,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Infallible;
type Future = AppServiceResponse<'a, F, Err>; type Future = BoxResponse<'a>;
#[inline] #[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let ready1 = self.filter.poll_ready(cx)?.is_ready(); let _ = ready!(self.filter.poll_ready(cx));
let ready2 = self.routing.poll_ready(cx)?.is_ready(); Poll::Ready(Ok(()))
if ready1 && ready2 {
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
} }
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, mut req: &'a mut WebRequest<'a, Err>) -> Self::Future {
AppServiceResponse { let r1 = unsafe { (req as *mut WebRequest<'a, Err>).as_mut().unwrap() };
filter: self.filter.call(req), let r2 = unsafe { (req as *mut WebRequest<'a, Err>).as_mut().unwrap() };
routing: self.routing.clone(),
endpoint: None,
}
}
}
pin_project_lite::pin_project! { let fut = self.filter.call(r1);
pub struct AppServiceResponse<'a, F: Service<&'a mut WebRequest<Err>>, Err: ErrorRenderer> { let router = self.router.clone();
#[pin]
filter: F::Future,
routing: Rc<AppRouting<'a, Err>>,
endpoint: Option<BoxResponse<'a, Err>>,
}
}
impl<'a, F, Err> Future for AppServiceResponse<'a, F, Err> Box::pin(async move {
where match fut.await {
F: Service< Ok(res) => (),
&'a mut WebRequest<Err>, Err(err) => return Ok(WebResponse::new(err.error_response(&req.req))),
Response = &'a mut WebRequest<Err>, }
Error = Err::Container,
>,
Err: ErrorRenderer,
{
type Output = Result<WebResponse, Err::Container>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let res = router.router.recognize_checked(req, |req, guards| {
let this = self.as_mut().project(); if let Some(guards) = guards {
for f in guards {
if !f.check(req.head()) {
return false;
}
}
}
true
});
if let Some(fut) = this.endpoint.as_mut() { if let Some((srv, _info)) = res {
Pin::new(fut).poll(cx) match srv.call(r2).await {
} else { Ok(res) => Ok(res),
let res = if let Poll::Ready(res) = this.filter.poll(cx) { Err(err) => Ok(WebResponse::new(err.error_response(&req.req))),
res? }
} else if let Some(ref default) = router.default {
match default.call(r2).await {
Ok(res) => Ok(res),
Err(err) => Ok(WebResponse::new(err.error_response(&req.req))),
}
} else { } else {
return Poll::Pending; Ok(WebResponse::new(Response::NotFound().finish()))
}; }
*this.endpoint = Some(this.routing.call(res)); })
self.poll(cx)
}
} }
} }

View file

@ -13,7 +13,7 @@ pub type BoxFactoryFuture<'a, Err: ErrorRenderer> =
pub type BoxService<'a, Err: ErrorRenderer> = Box< pub type BoxService<'a, Err: ErrorRenderer> = Box<
dyn Service< dyn Service<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
Future = BoxFuture<'a, Err>, Future = BoxFuture<'a, Err>,
@ -27,21 +27,21 @@ pub fn factory<'a, T, Err>(factory: T) -> BoxServiceFactory<'a, Err>
where where
Err: ErrorRenderer, Err: ErrorRenderer,
T: ServiceFactory< T: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
<T::Service as Service<&'a mut WebRequest<Err>>>::Future: 'a, <T::Service as Service<&'a mut WebRequest<'a, Err>>>::Future: 'a,
{ {
BoxServiceFactory(FactoryWrapper::boxed(factory)) BoxServiceFactory(FactoryWrapper::boxed(factory))
} }
type Inner<'a, Err: ErrorRenderer + 'static> = Box< type Inner<'a, Err: ErrorRenderer + 'static> = Box<
dyn ServiceFactory< dyn ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
@ -50,7 +50,7 @@ type Inner<'a, Err: ErrorRenderer + 'static> = Box<
> + 'static, > + 'static,
>; >;
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<Err>> impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>>
for BoxServiceFactory<'a, Err> for BoxServiceFactory<'a, Err>
{ {
type Response = WebResponse; type Response = WebResponse;
@ -73,14 +73,14 @@ impl<'a, T, Err> FactoryWrapper<T, Err>
where where
Err: ErrorRenderer + 'static, Err: ErrorRenderer + 'static,
T: ServiceFactory< T: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
<T::Service as Service<&'a mut WebRequest<Err>>>::Future: 'a, <T::Service as Service<&'a mut WebRequest<'a, Err>>>::Future: 'a,
{ {
fn boxed(factory: T) -> Inner<'a, Err> { fn boxed(factory: T) -> Inner<'a, Err> {
Box::new(Self { Box::new(Self {
@ -90,18 +90,18 @@ where
} }
} }
impl<'a, T, Err> ServiceFactory<&'a mut WebRequest<Err>> for FactoryWrapper<T, Err> impl<'a, T, Err> ServiceFactory<&'a mut WebRequest<'a, Err>> for FactoryWrapper<T, Err>
where where
Err: ErrorRenderer + 'static, Err: ErrorRenderer + 'static,
T: ServiceFactory< T: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
<T::Service as Service<&'a mut WebRequest<Err>>>::Future: 'a, <T::Service as Service<&'a mut WebRequest<'a, Err>>>::Future: 'a,
{ {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
@ -123,7 +123,7 @@ struct ServiceWrapper<T, Err>(T, PhantomData<Err>);
impl<'a, T, Err> ServiceWrapper<T, Err> impl<'a, T, Err> ServiceWrapper<T, Err>
where where
Err: ErrorRenderer, Err: ErrorRenderer,
T: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Err::Container> T: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Err::Container>
+ 'static, + 'static,
T::Future: 'a, T::Future: 'a,
{ {
@ -132,10 +132,10 @@ where
} }
} }
impl<'a, T, Err> Service<&'a mut WebRequest<Err>> for ServiceWrapper<T, Err> impl<'a, T, Err> Service<&'a mut WebRequest<'a, Err>> for ServiceWrapper<T, Err>
where where
Err: ErrorRenderer, Err: ErrorRenderer,
T: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Err::Container> T: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Err::Container>
+ 'static, + 'static,
T::Future: 'a, T::Future: 'a,
{ {
@ -154,7 +154,7 @@ where
} }
#[inline] #[inline]
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
Box::pin(self.0.call(req)) Box::pin(self.0.call(req))
} }
} }

View file

@ -4,7 +4,7 @@ use crate::router::ResourceDef;
use super::resource::Resource; use super::resource::Resource;
use super::route::Route; use super::route::Route;
use super::service::{AppServiceFactory, ServiceFactoryWrapper, WebServiceFactory}; use super::service::{create_web_service, WebService, WebServiceWrapper};
use super::types::state::{State, StateFactory}; use super::types::state::{State, StateFactory};
use super::{DefaultError, ErrorRenderer}; use super::{DefaultError, ErrorRenderer};
@ -60,7 +60,7 @@ impl Default for AppConfig {
/// to set of external methods. This could help with /// to set of external methods. This could help with
/// modularization of big application configuration. /// modularization of big application configuration.
pub struct ServiceConfig<'a, Err = DefaultError> { pub struct ServiceConfig<'a, Err = DefaultError> {
pub(super) services: Vec<Box<dyn AppServiceFactory<'a, Err>>>, pub(super) services: Vec<Box<dyn WebServiceWrapper<'a, Err>>>,
pub(super) state: Vec<Box<dyn StateFactory>>, pub(super) state: Vec<Box<dyn StateFactory>>,
pub(super) external: Vec<ResourceDef>, pub(super) external: Vec<ResourceDef>,
} }
@ -100,10 +100,9 @@ impl<'a, Err: ErrorRenderer> ServiceConfig<'a, Err> {
/// This is same as `App::service()` method. /// This is same as `App::service()` method.
pub fn service<F>(&mut self, factory: F) -> &mut Self pub fn service<F>(&mut self, factory: F) -> &mut Self
where where
F: WebServiceFactory<'a, Err> + 'static, F: WebService<'a, Err> + 'static,
{ {
self.services self.services.push(create_web_service(factory));
.push(Box::new(ServiceFactoryWrapper::new(factory)));
self self
} }
@ -136,7 +135,7 @@ mod tests {
#[crate::rt_test] #[crate::rt_test]
async fn test_configure_state() { async fn test_configure_state() {
let cfg = |cfg: &mut ServiceConfig<_>| { let cfg = |cfg: &mut ServiceConfig<'_, _>| {
cfg.state(10usize); cfg.state(10usize);
}; };

View file

@ -8,20 +8,20 @@ use crate::{http::Payload, util::Ready};
/// Trait implemented by types that can be extracted from request. /// Trait implemented by types that can be extracted from request.
/// ///
/// Types that implement this trait can be used with `Route` handlers. /// Types that implement this trait can be used with `Route` handlers.
pub trait FromRequest<Err>: Sized { pub trait FromRequest<'a, Err>: Sized {
/// The associated error which can be returned. /// The associated error which can be returned.
type Error; type Error;
/// Future that resolves to a Self /// Future that resolves to a Self
type Future: Future<Output = Result<Self, Self::Error>>; type Future: Future<Output = Result<Self, Self::Error>> + 'a;
/// Convert request to a Self /// Convert request to a Self
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future; fn from_request(req: &'a HttpRequest, payload: &'a mut Payload) -> Self::Future;
/// Convert request to a Self /// Convert request to a Self
/// ///
/// This method uses `Payload::None` as payload stream. /// This method uses `Payload::None` as payload stream.
fn extract(req: &HttpRequest) -> Self::Future { fn extract(req: &'a HttpRequest) -> Self::Future {
Self::from_request(req, &mut Payload::None) Self::from_request(req, &mut Payload::None)
} }
} }
@ -71,18 +71,18 @@ pub trait FromRequest<Err>: Sized {
/// ); /// );
/// } /// }
/// ``` /// ```
impl<T, Err> FromRequest<Err> for Option<T> impl<'a, T, Err> FromRequest<'a, Err> for Option<T>
where where
T: FromRequest<Err> + 'static, T: FromRequest<'a, Err> + 'static,
T::Future: 'static, T::Future: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
<T as FromRequest<Err>>::Error: Into<Err::Container>, <T as FromRequest<'a, Err>>::Error: Into<Err::Container>,
{ {
type Error = Err::Container; type Error = Err::Container;
type Future = Pin<Box<dyn Future<Output = Result<Option<T>, Self::Error>>>>; type Future = Pin<Box<dyn Future<Output = Result<Option<T>, Self::Error>> + 'a>>;
#[inline] #[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &'a HttpRequest, payload: &'a mut Payload) -> Self::Future {
let fut = T::from_request(req, payload); let fut = T::from_request(req, payload);
Box::pin(async move { Box::pin(async move {
match fut.await { match fut.await {
@ -139,18 +139,17 @@ where
/// ); /// );
/// } /// }
/// ``` /// ```
impl<T, E> FromRequest<E> for Result<T, T::Error> impl<'a, T, E> FromRequest<'a, E> for Result<T, T::Error>
where where
T: FromRequest<E> + 'static, T: FromRequest<'a, E> + 'static,
T::Error: 'static,
T::Future: 'static,
E: ErrorRenderer, E: ErrorRenderer,
{ {
type Error = T::Error; type Error = T::Error;
type Future = Pin<Box<dyn Future<Output = Result<Result<T, T::Error>, Self::Error>>>>; type Future =
Pin<Box<dyn Future<Output = Result<Result<T, T::Error>, Self::Error>> + 'a>>;
#[inline] #[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &'a HttpRequest, payload: &'a mut Payload) -> Self::Future {
let fut = T::from_request(req, payload); let fut = T::from_request(req, payload);
Box::pin(async move { Box::pin(async move {
match fut.await { match fut.await {
@ -162,7 +161,7 @@ where
} }
#[doc(hidden)] #[doc(hidden)]
impl<E: ErrorRenderer> FromRequest<E> for () { impl<'a, E: ErrorRenderer> FromRequest<'a, E> for () {
type Error = E::Container; type Error = E::Container;
type Future = Ready<(), E::Container>; type Future = Ready<(), E::Container>;
@ -175,14 +174,14 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
/// FromRequest implementation for a tuple /// FromRequest implementation for a tuple
#[allow(unused_parens)] #[allow(unused_parens)]
impl<Err: ErrorRenderer, $($T: FromRequest<Err> + 'static),+> FromRequest<Err> for ($($T,)+) impl<'a, Err: ErrorRenderer, $($T: FromRequest<'a, Err> + 'static),+> FromRequest<'a, Err> for ($($T,)+)
where where
$(<$T as $crate::web::FromRequest<Err>>::Error: Into<Err::Container>),+ $(<$T as $crate::web::FromRequest<'a, Err>>::Error: Into<Err::Container>),+
{ {
type Error = Err::Container; type Error = Err::Container;
type Future = $fut_type<Err, $($T),+>; type Future = $fut_type<'a, Err, $($T),+>;
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &'a HttpRequest, payload: &'a mut Payload) -> Self::Future {
$fut_type { $fut_type {
items: <($(Option<$T>,)+)>::default(), items: <($(Option<$T>,)+)>::default(),
$($T: $T::from_request(req, payload),)+ $($T: $T::from_request(req, payload),)+
@ -192,16 +191,16 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
#[doc(hidden)] #[doc(hidden)]
pub struct $fut_type<Err: ErrorRenderer, $($T: FromRequest<Err>),+> pub struct $fut_type<'a, Err: ErrorRenderer, $($T: FromRequest<'a, Err>),+>
{ {
items: ($(Option<$T>,)+), items: ($(Option<$T>,)+),
$(#[pin] $T: $T::Future),+ $(#[pin] $T: $T::Future),+
} }
} }
impl<Err: ErrorRenderer, $($T: FromRequest<Err>),+> Future for $fut_type<Err, $($T),+> impl<'a, Err: ErrorRenderer, $($T: FromRequest<'a, Err>),+> Future for $fut_type<'a, Err, $($T),+>
where where
$(<$T as $crate::web::FromRequest<Err>>::Error: Into<Err::Container>),+ $(<$T as $crate::web::FromRequest<'a, Err>>::Error: Into<Err::Container>),+
{ {
type Output = Result<($($T,)+), Err::Container>; type Output = Result<($($T,)+), Err::Container>;

View file

@ -38,7 +38,7 @@ where
pub(super) trait HandlerFn<Err: ErrorRenderer> { pub(super) trait HandlerFn<Err: ErrorRenderer> {
fn call<'b>( fn call<'b>(
&self, &self,
_: &'b mut WebRequest<Err>, _: &'b mut WebRequest<'b, Err>,
) -> Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'b>>; ) -> Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'b>>;
fn clone_handler(&self) -> Box<dyn HandlerFn<Err>>; fn clone_handler(&self) -> Box<dyn HandlerFn<Err>>;
@ -58,16 +58,16 @@ impl<F, T, Err> HandlerWrapper<F, T, Err> {
} }
} }
impl<F, T, Err> HandlerFn<Err> for HandlerWrapper<F, T, Err> impl<'a, F, T, Err> HandlerFn<Err> for HandlerWrapper<F, T, Err>
where where
F: Handler<T, Err>, F: Handler<T, Err>,
T: FromRequest<Err> + 'static, T: FromRequest<'a, Err> + 'static,
T::Error: Into<Err::Container>, T::Error: Into<Err::Container>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
fn call<'b>( fn call<'b>(
&self, &self,
req: &'b mut WebRequest<Err>, req: &'b mut WebRequest<'b, Err>,
) -> Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'b>> { ) -> Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'b>> {
let mut pl = Rc::get_mut(&mut (req.req).0).unwrap().payload.take(); let mut pl = Rc::get_mut(&mut (req.req).0).unwrap().payload.take();
let hnd = self.hnd.clone(); let hnd = self.hnd.clone();

View file

@ -1,4 +1,4 @@
use std::{cell::Ref, cell::RefCell, cell::RefMut, fmt, net, rc::Rc, rc::Weak}; use std::{cell::Ref, cell::RefCell, cell::RefMut, fmt, net, rc::Rc};
use crate::http::{ use crate::http::{
HeaderMap, HttpMessage, Message, Method, Payload, RequestHead, Uri, Version, HeaderMap, HttpMessage, Message, Method, Payload, RequestHead, Uri, Version,
@ -17,8 +17,6 @@ use super::rmap::ResourceMap;
/// An HTTP Request /// An HTTP Request
pub struct HttpRequest(pub(crate) Rc<HttpRequestInner>); pub struct HttpRequest(pub(crate) Rc<HttpRequestInner>);
pub(super) struct WeakHttpRequest(pub(super) Weak<HttpRequestInner>);
pub(crate) struct HttpRequestInner { pub(crate) struct HttpRequestInner {
pub(crate) head: Message<RequestHead>, pub(crate) head: Message<RequestHead>,
pub(crate) path: Path<Uri>, pub(crate) path: Path<Uri>,
@ -50,10 +48,6 @@ impl HttpRequest {
pool, pool,
})) }))
} }
pub(super) fn downgrade(&self) -> WeakHttpRequest {
WeakHttpRequest(Rc::downgrade(&self.0))
}
} }
impl HttpRequest { impl HttpRequest {

View file

@ -59,14 +59,14 @@ pub struct CompressMiddleware<S> {
encoding: ContentEncoding, encoding: ContentEncoding,
} }
impl<S, E> Service<WebRequest<E>> for CompressMiddleware<S> impl<'a, S, E> Service<WebRequest<E>> for CompressMiddleware<S>
where where
S: Service<WebRequest<E>, Response = WebResponse>, S: Service<WebRequest<E>, Response = WebResponse>,
E: ErrorRenderer, E: ErrorRenderer,
{ {
type Response = WebResponse; type Response = WebResponse;
type Error = S::Error; type Error = S::Error;
type Future = CompressResponse<S, E>; type Future = CompressResponse<'a, S, E>;
#[inline] #[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
@ -100,7 +100,7 @@ where
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
#[doc(hidden)] #[doc(hidden)]
pub struct CompressResponse<S: Service<WebRequest<E>>, E> pub struct CompressResponse<'a, S: Service<WebRequest<E>>, E>
{ {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
@ -109,7 +109,7 @@ pin_project_lite::pin_project! {
} }
} }
impl<S, E> Future for CompressResponse<S, E> impl<'a, S, E> Future for CompressResponse<'a, S, E>
where where
S: Service<WebRequest<E>, Response = WebResponse>, S: Service<WebRequest<E>, Response = WebResponse>,
E: ErrorRenderer, E: ErrorRenderer,

View file

@ -5,7 +5,7 @@ use std::{convert::Infallible, convert::TryFrom, future::Future, pin::Pin, rc::R
use crate::http::error::HttpError; use crate::http::error::HttpError;
use crate::http::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE}; use crate::http::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
use crate::service::{Service, Transform}; use crate::service::{Service, Transform};
use crate::web::{WebRequest, WebResponse}; use crate::web::{WebRequest, WebResponse, ErrorRenderer};
/// `Middleware` for setting default response headers. /// `Middleware` for setting default response headers.
/// ///
@ -102,14 +102,15 @@ pub struct DefaultHeadersMiddleware<S> {
inner: Rc<Inner>, inner: Rc<Inner>,
} }
impl<S, E> Service<WebRequest<E>> for DefaultHeadersMiddleware<S> impl<'a, S, E> Service<WebRequest<E>> for DefaultHeadersMiddleware<S>
where where
S: Service<WebRequest<E>, Response = WebResponse, Error = Infallible>, S: Service<WebRequest<E>, Response = WebResponse, Error = Infallible>,
S::Future: 'static, S::Future: 'static,
E: ErrorRenderer,
{ {
type Response = WebResponse; type Response = WebResponse;
type Error = Infallible; type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + 'a>>;
#[inline] #[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {

View file

@ -130,13 +130,14 @@ pub struct LoggerMiddleware<S> {
service: S, service: S,
} }
impl<S, E> Service<WebRequest<E>> for LoggerMiddleware<S> impl<'a, S, E> Service<WebRequest<E>> for LoggerMiddleware<S>
where where
S: Service<WebRequest<E>, Response = WebResponse>, S: Service<WebRequest<E>, Response = WebResponse>,
E: 'static,
{ {
type Response = WebResponse; type Response = WebResponse;
type Error = S::Error; type Error = S::Error;
type Future = Either<LoggerResponse<S, E>, S::Future>; type Future = Either<LoggerResponse<'a, S, E>, S::Future>;
#[inline] #[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
@ -171,7 +172,7 @@ where
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
#[doc(hidden)] #[doc(hidden)]
pub struct LoggerResponse<S: Service<WebRequest<E>>, E> pub struct LoggerResponse<'a, S: Service<WebRequest<E>>, E>
{ {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
@ -181,7 +182,7 @@ pin_project_lite::pin_project! {
} }
} }
impl<S, E> Future for LoggerResponse<S, E> impl<'a, S, E> Future for LoggerResponse<'a, S, E>
where where
S: Service<WebRequest<E>, Response = WebResponse>, S: Service<WebRequest<E>, Response = WebResponse>,
{ {

View file

@ -79,7 +79,7 @@ pub mod guard;
mod handler; mod handler;
mod httprequest; mod httprequest;
mod info; mod info;
pub mod middleware; //pub mod middleware;
mod request; mod request;
mod resource; mod resource;
mod responder; mod responder;
@ -91,7 +91,7 @@ mod boxed;
mod server; mod server;
mod service; mod service;
mod stack; mod stack;
pub mod test; //pub mod test;
pub mod types; pub mod types;
mod util; mod util;
pub mod ws; pub mod ws;
@ -125,7 +125,7 @@ pub use self::response::WebResponse;
pub use self::route::Route; pub use self::route::Route;
// pub use self::scope::Scope; // pub use self::scope::Scope;
pub use self::server::HttpServer; pub use self::server::HttpServer;
pub use self::service::WebServiceFactory; pub use self::service::{WebService, WebServiceConfig};
pub use self::util::*; pub use self::util::*;
pub mod dev { pub mod dev {
@ -139,7 +139,7 @@ pub mod dev {
pub use crate::web::info::ConnectionInfo; pub use crate::web::info::ConnectionInfo;
pub use crate::web::rmap::ResourceMap; pub use crate::web::rmap::ResourceMap;
pub use crate::web::route::IntoRoutes; pub use crate::web::route::IntoRoutes;
pub use crate::web::service::{WebServiceAdapter, WebServiceConfig, WebServiceFactory}; pub use crate::web::service::{WebService, WebServiceAdapter, WebServiceConfig};
pub use crate::web::stack::Stack; pub use crate::web::stack::Stack;
pub(crate) fn insert_slash(mut patterns: Vec<String>) -> Vec<String> { pub(crate) fn insert_slash(mut patterns: Vec<String>) -> Vec<String> {
@ -151,55 +151,55 @@ pub mod dev {
patterns patterns
} }
// #[doc(hidden)] #[doc(hidden)]
// #[inline(always)] #[inline(always)]
// pub fn __assert_extractor<'a, Err, T>() pub fn __assert_extractor<'a, Err, T>()
// where where
// T: super::FromRequest<'a, Err>, T: super::FromRequest<'a, Err>,
// Err: super::ErrorRenderer, Err: super::ErrorRenderer,
// <T as super::FromRequest<'a, Err>>::Error: Into<Err::Container>, <T as super::FromRequest<'a, Err>>::Error: Into<Err::Container>,
// { {
// } }
// #[doc(hidden)] #[doc(hidden)]
// #[inline(always)] #[inline(always)]
// pub fn __assert_handler<Err, Fun, Fut>( pub fn __assert_handler<Err, Fun, Fut>(
// f: Fun, f: Fun,
// ) -> impl Handler<(), Err, Future = Fut, Output = Fut::Output> ) -> impl Handler<(), Err, Future = Fut, Output = Fut::Output>
// where where
// Err: super::ErrorRenderer, Err: super::ErrorRenderer,
// Fun: Fn() -> Fut + Clone + 'static, Fun: Fn() -> Fut + Clone + 'static,
// Fut: std::future::Future + 'static, Fut: std::future::Future + 'static,
// Fut::Output: super::Responder<Err>, Fut::Output: super::Responder<Err>,
// { {
// f f
// } }
// macro_rules! assert_handler ({ $name:ident, $($T:ident),+} => { macro_rules! assert_handler ({ $name:ident, $($T:ident),+} => {
// #[doc(hidden)] #[doc(hidden)]
// #[inline(always)] #[inline(always)]
// pub fn $name<'a, Err, Fun, Fut, $($T,)+>( pub fn $name<'a, Err, Fun, Fut, $($T,)+>(
// f: Fun, f: Fun,
// ) -> impl Handler<($($T,)+), Err, Future = Fut, Output = Fut::Output> ) -> impl Handler<($($T,)+), Err, Future = Fut, Output = Fut::Output>
// where where
// Err: $crate::web::ErrorRenderer, Err: $crate::web::ErrorRenderer,
// Fun: Fn($($T,)+) -> Fut + Clone + 'static, Fun: Fn($($T,)+) -> Fut + Clone + 'static,
// Fut: std::future::Future + 'static, Fut: std::future::Future + 'static,
// Fut::Output: $crate::web::Responder<Err>, Fut::Output: $crate::web::Responder<Err>,
// $($T: $crate::web::FromRequest<'a, Err>),+, $($T: $crate::web::FromRequest<'a, Err>),+,
// { {
// f f
// } }
// }); });
// assert_handler!(__assert_handler1, A); assert_handler!(__assert_handler1, A);
// assert_handler!(__assert_handler2, A, B); assert_handler!(__assert_handler2, A, B);
// assert_handler!(__assert_handler3, A, B, C); assert_handler!(__assert_handler3, A, B, C);
// assert_handler!(__assert_handler4, A, B, C, D); assert_handler!(__assert_handler4, A, B, C, D);
// assert_handler!(__assert_handler5, A, B, C, D, E); assert_handler!(__assert_handler5, A, B, C, D, E);
// assert_handler!(__assert_handler6, A, B, C, D, E, F); assert_handler!(__assert_handler6, A, B, C, D, E, F);
// assert_handler!(__assert_handler7, A, B, C, D, E, F, G); assert_handler!(__assert_handler7, A, B, C, D, E, F, G);
// assert_handler!(__assert_handler8, A, B, C, D, E, F, G, H); assert_handler!(__assert_handler8, A, B, C, D, E, F, G, H);
// assert_handler!(__assert_handler9, A, B, C, D, E, F, G, H, I); assert_handler!(__assert_handler9, A, B, C, D, E, F, G, H, I);
// assert_handler!(__assert_handler10, A, B, C, D, E, F, G, H, I, J); assert_handler!(__assert_handler10, A, B, C, D, E, F, G, H, I, J);
} }

View file

@ -9,7 +9,7 @@ use crate::util::Extensions;
use super::config::AppConfig; use super::config::AppConfig;
use super::error::{ErrorRenderer, WebResponseError}; use super::error::{ErrorRenderer, WebResponseError};
use super::httprequest::{HttpRequest, WeakHttpRequest}; use super::httprequest::HttpRequest;
use super::info::ConnectionInfo; use super::info::ConnectionInfo;
use super::response::WebResponse; use super::response::WebResponse;
use super::rmap::ResourceMap; use super::rmap::ResourceMap;
@ -17,12 +17,12 @@ use super::rmap::ResourceMap;
/// An service http request /// An service http request
/// ///
/// WebRequest allows mutable access to request's internal structures /// WebRequest allows mutable access to request's internal structures
pub struct WebRequest<Err> { pub struct WebRequest<'a, Err> {
pub(super) req: HttpRequest, pub(super) req: &'a mut HttpRequest,
_t: PhantomData<Err>, _marker: PhantomData<fn(&'a ()) -> &'a Err>,
} }
impl<Err: ErrorRenderer> WebRequest<Err> { impl<'a, Err: ErrorRenderer> WebRequest<'a, Err> {
/// Create web response for error /// Create web response for error
#[inline] #[inline]
pub fn render_error<E: WebResponseError<Err>>(self, err: E) -> WebResponse { pub fn render_error<E: WebResponseError<Err>>(self, err: E) -> WebResponse {
@ -36,52 +36,48 @@ impl<Err: ErrorRenderer> WebRequest<Err> {
} }
} }
impl<Err> WebRequest<Err> { impl<'a, Err> WebRequest<'a, Err> {
/// Construct web request /// Construct web request
pub(crate) fn new(req: HttpRequest) -> Self { pub(crate) fn new(req: &'a mut HttpRequest) -> Self {
WebRequest { WebRequest {
req, req,
_t: PhantomData, _marker: PhantomData,
} }
} }
pub(super) fn weak_request(&self) -> WeakHttpRequest { // /// Deconstruct request into parts
self.req.downgrade() // pub fn into_parts(mut self) -> (HttpRequest, Payload) {
} // let pl = Rc::get_mut(&mut (self.req).0).unwrap().payload.take();
// (self.req, pl)
// }
/// Deconstruct request into parts // /// Construct request from parts.
pub fn into_parts(mut self) -> (HttpRequest, Payload) { // ///
let pl = Rc::get_mut(&mut (self.req).0).unwrap().payload.take(); // /// `WebRequest` can be re-constructed only if `req` hasnt been cloned.
(self.req, pl) // pub fn from_parts(
} // mut req: HttpRequest,
// pl: Payload,
// ) -> Result<Self, (HttpRequest, Payload)> {
// if Rc::strong_count(&req.0) == 1 {
// Rc::get_mut(&mut req.0).unwrap().payload = pl;
// Ok(WebRequest::new(req))
// } else {
// Err((req, pl))
// }
// }
/// Construct request from parts. // /// Construct request from request.
/// // ///
/// `WebRequest` can be re-constructed only if `req` hasnt been cloned. // /// `HttpRequest` implements `Clone` trait via `Rc` type. `WebRequest`
pub fn from_parts( // /// can be re-constructed only if rc's strong pointers count eq 1 and
mut req: HttpRequest, // /// weak pointers count is 0.
pl: Payload, // pub fn from_request(req: HttpRequest) -> Result<Self, HttpRequest> {
) -> Result<Self, (HttpRequest, Payload)> { // if Rc::strong_count(&req.0) == 1 {
if Rc::strong_count(&req.0) == 1 { // Ok(WebRequest::new(req))
Rc::get_mut(&mut req.0).unwrap().payload = pl; // } else {
Ok(WebRequest::new(req)) // Err(req)
} else { // }
Err((req, pl)) // }
}
}
/// Construct request from request.
///
/// `HttpRequest` implements `Clone` trait via `Rc` type. `WebRequest`
/// can be re-constructed only if rc's strong pointers count eq 1 and
/// weak pointers count is 0.
pub fn from_request(req: HttpRequest) -> Result<Self, HttpRequest> {
if Rc::strong_count(&req.0) == 1 {
Ok(WebRequest::new(req))
} else {
Err(req)
}
}
/// Create web response /// Create web response
#[inline] #[inline]
@ -245,7 +241,7 @@ impl<Err> WebRequest<Err> {
} }
} }
impl<Err> Resource<Uri> for WebRequest<Err> { impl<'a, Err> Resource<Uri> for WebRequest<'a, Err> {
fn path(&self) -> &str { fn path(&self) -> &str {
self.match_info().path() self.match_info().path()
} }
@ -255,7 +251,7 @@ impl<Err> Resource<Uri> for WebRequest<Err> {
} }
} }
impl<Err> HttpMessage for WebRequest<Err> { impl<'a, Err> HttpMessage for WebRequest<'a, Err> {
#[inline] #[inline]
/// Returns Request's headers. /// Returns Request's headers.
fn message_headers(&self) -> &HeaderMap { fn message_headers(&self) -> &HeaderMap {
@ -275,7 +271,7 @@ impl<Err> HttpMessage for WebRequest<Err> {
} }
} }
impl<Err: ErrorRenderer> fmt::Debug for WebRequest<Err> { impl<'a, Err: ErrorRenderer> fmt::Debug for WebRequest<'a, Err> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!( writeln!(
f, f,

View file

@ -9,7 +9,7 @@ use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Tran
use crate::util::{Either, Extensions, Ready}; use crate::util::{Either, Extensions, Ready};
use super::boxed::{self, BoxService, BoxServiceFactory}; use super::boxed::{self, BoxService, BoxServiceFactory};
use super::dev::{insert_slash, WebServiceConfig, WebServiceFactory}; use super::dev::{insert_slash, WebService, WebServiceConfig};
use super::extract::FromRequest; use super::extract::FromRequest;
use super::route::{IntoRoutes, Route, RouteService}; use super::route::{IntoRoutes, Route, RouteService};
use super::stack::{ use super::stack::{
@ -39,9 +39,9 @@ use super::{guard::Guard, types::State, ErrorRenderer, Handler, WebRequest, WebR
/// ///
/// If no matching route could be found, *405* response code get returned. /// If no matching route could be found, *405* response code get returned.
/// Default behavior could be overriden with `default_resource()` method. /// Default behavior could be overriden with `default_resource()` method.
pub struct Resource<Err: ErrorRenderer, M = Identity, F = Filter<Err>> { pub struct Resource<Err: ErrorRenderer, M = Identity, F = Filter> {
middleware: M,
filter: F, filter: F,
middleware: M,
rdef: Vec<String>, rdef: Vec<String>,
name: Option<String>, name: Option<String>,
routes: Vec<Route<Err>>, routes: Vec<Route<Err>>,
@ -56,8 +56,8 @@ impl<'a, Err: ErrorRenderer> Resource<Err> {
routes: Vec::new(), routes: Vec::new(),
rdef: path.patterns(), rdef: path.patterns(),
name: None, name: None,
filter: Filter,
middleware: Identity, middleware: Identity,
filter: Filter::new(),
guards: Vec::new(), guards: Vec::new(),
state: None, state: None,
default: Route::new().to(|| async { Response::MethodNotAllowed().finish() }), default: Route::new().to(|| async { Response::MethodNotAllowed().finish() }),
@ -228,7 +228,7 @@ where
/// Register request filter. /// Register request filter.
/// ///
/// This is similar to `App's` filters, but filter get invoked on resource level. /// This is similar to `App's` filters, but filter get invoked on resource level.
pub fn filter<U>(self, filter: U) -> Resource<Err, M, Filters<F, U, Err>> { pub fn filter<U>(self, filter: U) -> Resource<Err, M, Filters<F, U>> {
Resource { Resource {
filter: Filters::new(self.filter, filter), filter: Filters::new(self.filter, filter),
middleware: self.middleware, middleware: self.middleware,
@ -248,7 +248,7 @@ where
/// type (i.e modify response's body). /// type (i.e modify response's body).
/// ///
/// **Note**: middlewares get called in opposite order of middlewares registration. /// **Note**: middlewares get called in opposite order of middlewares registration.
pub fn wrap<U>(self, mw: U) -> Resource<Err, Stack<M, U, Err>, F> { pub fn wrap<U>(self, mw: U) -> Resource<Err, Stack<M, U>, F> {
Resource { Resource {
middleware: Stack::new(self.middleware, mw), middleware: Stack::new(self.middleware, mw),
filter: self.filter, filter: self.filter,
@ -275,22 +275,21 @@ where
} }
} }
impl<'a, Err, M, F> WebServiceFactory<'a, Err> for Resource<Err, M, F> impl<'a, Err, M, F> WebService<'a, Err> for Resource<Err, M, F>
where where
M: Transform< M: Transform<
Next< Next<
ResourceService< ResourceService<
<F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err, Err,
>, >,
Err,
>, >,
> + 'static, > + 'static,
M::Service: M::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: FiltersFactory<'a, Err>, F: FiltersFactory<'a, Err> + 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service: 'static, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Future: 'static, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
fn register(mut self, config: &mut WebServiceConfig<'a, Err>) { fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
@ -331,50 +330,41 @@ where
} }
} }
// impl<'a, Err, M, F> Resource<Err, M, F> impl<'a, Err, M, F>
// where IntoServiceFactory<
// F: FiltersFactory<'a, Err>, ResourceServiceFactory<Err, M, F::Service>,
// M: Transform<Next<ResourceService<'a, <F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service, Err>, Err>> + 'static, &'a mut WebRequest<'a, Err>,
// M::Service: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, > for Resource<Err, M, F>
// Err: ErrorRenderer, where
// { M: Transform<
// pub fn finish(self) -> impl ServiceFactory<&'a mut WebRequest<Err>, Response = WebResponse, Error = Err::Container, InitError = ()> { Next<
// let router_factory = ResourceRouterFactory { ResourceService<
// routes: self.routes, <F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
// state: self.state.map(Rc::new), Err,
// default: self.default, >,
// }; >,
> + 'static,
M::Service:
Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: FiltersFactory<'a, Err> + 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
Err: ErrorRenderer,
{
fn into_factory(self) -> ResourceServiceFactory<Err, M, F::Service> {
let router_factory = ResourceRouterFactory {
routes: self.routes,
state: self.state.map(Rc::new),
default: self.default,
};
// ResourceServiceFactory::<'a, Err, _, _> { ResourceServiceFactory {
// middleware: Rc::new(MiddlewareStack::new(self.middleware)), middleware: Rc::new(MiddlewareStack::new(self.middleware)),
// filter: self.filter.create(), filter: self.filter.create(),
// routing: router_factory, routing: router_factory,
// } }
// } }
// } }
// impl<'a, Err, M, F>
// IntoServiceFactory<ResourceServiceFactory<'a, Err, M, F::Service>, &'a mut WebRequest<Err>> for Resource<Err, M, F>
// where
// F: FiltersFactory<'a, Err>,
// M: Transform<Next<ResourceService<'a, <F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service, Err>, Err>> + 'static,
// M::Service: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
// Err: ErrorRenderer,
// {
// fn into_factory(self) -> ResourceServiceFactory<'a, Err, M, F::Service> {
// let router_factory = ResourceRouterFactory {
// routes: self.routes,
// state: self.state.map(Rc::new),
// default: self.default,
// };
// ResourceServiceFactory {
// middleware: Rc::new(MiddlewareStack::new(self.middleware)),
// filter: self.filter.create(),
// routing: router_factory,
// }
// }
// }
/// Resource service /// Resource service
pub struct ResourceServiceFactory<Err: ErrorRenderer, M, F> { pub struct ResourceServiceFactory<Err: ErrorRenderer, M, F> {
@ -383,15 +373,15 @@ pub struct ResourceServiceFactory<Err: ErrorRenderer, M, F> {
routing: ResourceRouterFactory<Err>, routing: ResourceRouterFactory<Err>,
} }
impl<'a, Err, M, F> ServiceFactory<&'a mut WebRequest<Err>> impl<'a, Err, M, F> ServiceFactory<&'a mut WebRequest<'a, Err>>
for ResourceServiceFactory<Err, M, F> for ResourceServiceFactory<Err, M, F>
where where
M: Transform<Next<ResourceService<F::Service, Err>, Err>> + 'static, M: Transform<Next<ResourceService<F::Service, Err>>> + 'static,
M::Service: M::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: ServiceFactory< F: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
@ -423,11 +413,11 @@ pub struct ResourceService<F, Err: ErrorRenderer> {
routing: Rc<ResourceRouter<Err>>, routing: Rc<ResourceRouter<Err>>,
} }
impl<'a, F, Err> Service<&'a mut WebRequest<Err>> for ResourceService<F, Err> impl<'a, F, Err> Service<&'a mut WebRequest<'a, Err>> for ResourceService<F, Err>
where where
F: Service< F: Service<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
>, >,
Err: ErrorRenderer, Err: ErrorRenderer,
@ -447,7 +437,7 @@ where
} }
} }
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
ResourceServiceResponse { ResourceServiceResponse {
filter: self.filter.call(req), filter: self.filter.call(req),
routing: self.routing.clone(), routing: self.routing.clone(),
@ -457,19 +447,19 @@ where
} }
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
pub struct ResourceServiceResponse<'a, F: Service<&'a mut WebRequest<Err>>, Err: ErrorRenderer> { pub struct ResourceServiceResponse<'a, F: Service<&'a mut WebRequest<'a, Err>>, Err: ErrorRenderer> {
#[pin] #[pin]
filter: F::Future, filter: F::Future,
routing: Rc<ResourceRouter<Err>>, routing: Rc<ResourceRouter<Err>>,
endpoint: Option<<ResourceRouter<Err> as Service<&'a mut WebRequest<Err>>>::Future>, endpoint: Option<<ResourceRouter<Err> as Service<&'a mut WebRequest<'a, Err>>>::Future>,
} }
} }
impl<'a, F, Err> Future for ResourceServiceResponse<'a, F, Err> impl<'a, F, Err> Future for ResourceServiceResponse<'a, F, Err>
where where
F: Service< F: Service<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
>, >,
Err: ErrorRenderer, Err: ErrorRenderer,
@ -499,7 +489,7 @@ struct ResourceRouterFactory<Err: ErrorRenderer> {
default: Route<Err>, default: Route<Err>,
} }
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<Err>> impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>>
for ResourceRouterFactory<Err> for ResourceRouterFactory<Err>
{ {
type Response = WebResponse; type Response = WebResponse;
@ -527,7 +517,7 @@ struct ResourceRouter<Err: ErrorRenderer> {
default: RouteService<Err>, default: RouteService<Err>,
} }
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for ResourceRouter<Err> { impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for ResourceRouter<Err> {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type Future = Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'a>>; type Future = Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'a>>;
@ -537,7 +527,7 @@ impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for ResourceRouter
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
fn call(&self, mut req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, mut req: &'a mut WebRequest<'a, Err>) -> Self::Future {
for route in self.routes.iter() { for route in self.routes.iter() {
if route.check(req) { if route.check(req) {
if let Some(ref state) = self.state { if let Some(ref state) = self.state {

View file

@ -8,8 +8,7 @@ use super::httprequest::HttpRequest;
/// An service http response /// An service http response
pub struct WebResponse { pub struct WebResponse {
// request: HttpRequest, pub(super) response: Response<Body>,
response: Response<Body>,
} }
impl WebResponse { impl WebResponse {
@ -21,10 +20,10 @@ impl WebResponse {
/// Create web response from the error /// Create web response from the error
pub fn from_err<Err: ErrorRenderer, E: Into<Err::Container>>( pub fn from_err<Err: ErrorRenderer, E: Into<Err::Container>>(
err: E, err: E,
request: HttpRequest, request: &HttpRequest,
) -> Self { ) -> Self {
let err = err.into(); let err = err.into();
let res: Response = err.error_response(&request); let res: Response = err.error_response(request);
if res.head().status == StatusCode::INTERNAL_SERVER_ERROR { if res.head().status == StatusCode::INTERNAL_SERVER_ERROR {
log::error!("Internal Server Error: {:?}", err); log::error!("Internal Server Error: {:?}", err);
@ -37,29 +36,12 @@ impl WebResponse {
} }
} }
/// Create web response for error
#[inline]
pub fn error_response<Err: ErrorRenderer, E: Into<Err::Container>>(
self,
err: E,
) -> Self {
// Self::from_err::<Err, E>(err) //, self.request)
todo!()
}
/// Create web response /// Create web response
#[inline] #[inline]
pub fn into_response(self, response: Response) -> WebResponse { pub fn into_response(self, response: Response) -> WebResponse {
WebResponse::new(response) WebResponse::new(response)
} }
/// Get reference to original request
#[inline]
pub fn request(&self) -> &HttpRequest {
//&self.request
todo!()
}
/// Get reference to response /// Get reference to response
#[inline] #[inline]
pub fn response(&self) -> &Response<Body> { pub fn response(&self) -> &Response<Body> {
@ -90,21 +72,6 @@ impl WebResponse {
self.response.headers_mut() self.response.headers_mut()
} }
/// Execute closure and in case of error convert it to response.
pub fn checked_expr<Err, F, E>(mut self, f: F) -> Self
where
F: FnOnce(&mut Self) -> Result<(), E>,
E: Into<Err::Container>,
Err: ErrorRenderer,
{
if let Err(err) = f(&mut self) {
let res: Response = err.into().into();
WebResponse::new(res) //, self.request)
} else {
self
}
}
/// Extract response body /// Extract response body
pub fn take_body(&mut self) -> ResponseBody<Body> { pub fn take_body(&mut self) -> ResponseBody<Body> {
self.response.take_body() self.response.take_body()
@ -115,21 +82,22 @@ impl WebResponse {
where where
F: FnOnce(&mut ResponseHead, ResponseBody<Body>) -> ResponseBody<Body>, F: FnOnce(&mut ResponseHead, ResponseBody<Body>) -> ResponseBody<Body>,
{ {
let response = self.response.map_body(f);
WebResponse { WebResponse {
response, response: self.response.map_body(f),
// request: self.request,
} }
} }
} }
impl From<Response<Body>> for WebResponse {
#[inline]
fn from(response: Response<Body>) -> WebResponse {
WebResponse { response }
}
}
impl From<WebResponse> for Response<Body> { impl From<WebResponse> for Response<Body> {
fn from(mut res: WebResponse) -> Response<Body> { #[inline]
let head = res.response.head_mut(); fn from(res: WebResponse) -> Response<Body> {
// if res.request.head().upgrade() {
// head.set_io(res.request.head());
// }
res.response res.response
} }
} }

View file

@ -46,7 +46,7 @@ impl<'a, Err: ErrorRenderer> Route<Err> {
} }
} }
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<Err>> for Route<Err> { impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>> for Route<Err> {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type InitError = (); type InitError = ();
@ -65,7 +65,7 @@ pub struct RouteService<Err: ErrorRenderer> {
} }
impl<Err: ErrorRenderer> RouteService<Err> { impl<Err: ErrorRenderer> RouteService<Err> {
pub fn check(&self, req: &mut WebRequest<Err>) -> bool { pub fn check(&self, req: &'_ mut WebRequest<'_, Err>) -> bool {
if !self.methods.is_empty() && !self.methods.contains(&req.head().method) { if !self.methods.is_empty() && !self.methods.contains(&req.head().method) {
return false; return false;
} }
@ -79,7 +79,7 @@ impl<Err: ErrorRenderer> RouteService<Err> {
} }
} }
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for RouteService<Err> { impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for RouteService<Err> {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + 'a>>; type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + 'a>>;
@ -90,7 +90,7 @@ impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for RouteService<E
} }
#[inline] #[inline]
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
self.handler.call(req) self.handler.call(req)
} }
} }
@ -181,7 +181,7 @@ impl<Err: ErrorRenderer> Route<Err> {
pub fn to<F, Args>(mut self, handler: F) -> Self pub fn to<F, Args>(mut self, handler: F) -> Self
where where
F: Handler<Args, Err>, F: Handler<Args, Err>,
Args: FromRequest<Err> + 'static, Args: FromRequest<'a, Err> + 'static,
Args::Error: Into<Err::Container>, Args::Error: Into<Err::Container>,
{ {
self.handler = Box::new(HandlerWrapper::new(handler)); self.handler = Box::new(HandlerWrapper::new(handler));

View file

@ -19,9 +19,9 @@ use super::{ErrorRenderer, Resource, Route, WebRequest, WebResponse};
type Guards = Vec<Box<dyn Guard>>; type Guards = Vec<Box<dyn Guard>>;
type HttpService<Err: ErrorRenderer> = type HttpService<Err: ErrorRenderer> =
BoxService<WebRequest<Err>, WebResponse, Err::Container>; BoxService<&'a mut WebRequest<'a, Err>, WebResponse, Err::Container>;
type HttpNewService<Err: ErrorRenderer> = type HttpNewService<Err: ErrorRenderer> =
BoxServiceFactory<(), WebRequest<Err>, WebResponse, Err::Container, ()>; BoxServiceFactory<(), &'a mut WebRequest<'a, Err>, WebResponse, Err::Container, ()>;
type BoxResponse<Err: ErrorRenderer> = type BoxResponse<Err: ErrorRenderer> =
Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>>>>; Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>>>>;
@ -56,7 +56,7 @@ type BoxResponse<Err: ErrorRenderer> =
/// ///
pub struct Scope<Err: ErrorRenderer, M = Identity, T = Filter<Err>> { pub struct Scope<Err: ErrorRenderer, M = Identity, T = Filter<Err>> {
middleware: M, middleware: M,
filter: PipelineFactory<T, WebRequest<Err>>, filter: PipelineFactory<T, &'a mut WebRequest<'a, Err>>,
rdef: Vec<String>, rdef: Vec<String>,
state: Option<Extensions>, state: Option<Extensions>,
services: Vec<Box<dyn AppServiceFactory<Err>>>, services: Vec<Box<dyn AppServiceFactory<Err>>>,
@ -86,8 +86,8 @@ impl<Err: ErrorRenderer> Scope<Err> {
impl<Err, M, T> Scope<Err, M, T> impl<Err, M, T> Scope<Err, M, T>
where where
T: ServiceFactory< T: ServiceFactory<
WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
>, >,
@ -286,8 +286,8 @@ where
/// If default resource is not registered, app's default resource is being used. /// If default resource is not registered, app's default resource is being used.
pub fn default_service<F, S>(mut self, f: F) -> Self pub fn default_service<F, S>(mut self, f: F) -> Self
where where
F: IntoServiceFactory<S, WebRequest<Err>>, F: IntoServiceFactory<S, &'a mut WebRequest<'a, Err>>,
S: ServiceFactory<WebRequest<Err>, Response = WebResponse, Error = Err::Container> S: ServiceFactory<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Err::Container>
+ 'static, + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
{ {
@ -314,20 +314,20 @@ where
Err, Err,
M, M,
impl ServiceFactory< impl ServiceFactory<
WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
>, >,
> >
where where
U: ServiceFactory< U: ServiceFactory<
WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
>, >,
F: IntoServiceFactory<U, WebRequest<Err>>, F: IntoServiceFactory<U, &'a mut WebRequest<'a, Err>>,
{ {
Scope { Scope {
filter: self.filter.and_then(filter.into_factory()), filter: self.filter.and_then(filter.into_factory()),
@ -370,13 +370,13 @@ where
impl<Err, M, T> WebServiceFactory<Err> for Scope<Err, M, T> impl<Err, M, T> WebServiceFactory<Err> for Scope<Err, M, T>
where where
T: ServiceFactory< T: ServiceFactory<
WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
M: Transform<Next<ScopeService<T::Service, Err>, Err>> + 'static, M: Transform<Next<ScopeService<T::Service, Err>, Err>> + 'static,
M::Service: Service<WebRequest<Err>, Response = WebResponse, Error = Infallible>, M::Service: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
fn register(mut self, config: &mut WebServiceConfig<Err>) { fn register(mut self, config: &mut WebServiceConfig<Err>) {
@ -456,13 +456,13 @@ struct ScopeServiceFactory<M, F, Err: ErrorRenderer> {
routing: ScopeRouterFactory<Err>, routing: ScopeRouterFactory<Err>,
} }
impl<M, F, Err> ServiceFactory<WebRequest<Err>> for ScopeServiceFactory<M, F, Err> impl<M, F, Err> ServiceFactory<&'a mut WebRequest<'a, Err>> for ScopeServiceFactory<M, F, Err>
where where
M: Transform<Next<ScopeService<F::Service, Err>, Err>> + 'static, M: Transform<Next<ScopeService<F::Service, Err>, Err>> + 'static,
M::Service: Service<WebRequest<Err>, Response = WebResponse, Error = Infallible>, M::Service: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: ServiceFactory< F: ServiceFactory<
WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
@ -492,9 +492,9 @@ pub struct ScopeService<F, Err: ErrorRenderer> {
routing: Rc<ScopeRouter<Err>>, routing: Rc<ScopeRouter<Err>>,
} }
impl<F, Err> Service<WebRequest<Err>> for ScopeService<F, Err> impl<F, Err> Service<&'a mut WebRequest<'a, Err>> for ScopeService<F, Err>
where where
F: Service<WebRequest<Err>, Response = WebRequest<Err>, Error = Err::Container>, F: Service<&'a mut WebRequest<'a, Err>, Response = &'a mut WebRequest<'a, Err>, Error = Err::Container>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
type Response = WebResponse; type Response = WebResponse;
@ -512,7 +512,7 @@ where
} }
} }
fn call(&self, req: WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
ScopeServiceResponse { ScopeServiceResponse {
filter: self.filter.call(req), filter: self.filter.call(req),
routing: self.routing.clone(), routing: self.routing.clone(),
@ -522,17 +522,17 @@ where
} }
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
pub struct ScopeServiceResponse<F: Service<WebRequest<Err>>, Err: ErrorRenderer> { pub struct ScopeServiceResponse<F: Service<&'a mut WebRequest<'a, Err>>, Err: ErrorRenderer> {
#[pin] #[pin]
filter: F::Future, filter: F::Future,
routing: Rc<ScopeRouter<Err>>, routing: Rc<ScopeRouter<Err>>,
endpoint: Option<<ScopeRouter<Err> as Service<WebRequest<Err>>>::Future>, endpoint: Option<<ScopeRouter<Err> as Service<&'a mut WebRequest<'a, Err>>>::Future>,
} }
} }
impl<F, Err> Future for ScopeServiceResponse<F, Err> impl<F, Err> Future for ScopeServiceResponse<F, Err>
where where
F: Service<WebRequest<Err>, Response = WebRequest<Err>, Error = Err::Container>, F: Service<&'a mut WebRequest<'a, Err>, Response = &'a mut WebRequest<'a, Err>, Error = Err::Container>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
type Output = Result<WebResponse, Err::Container>; type Output = Result<WebResponse, Err::Container>;
@ -561,7 +561,7 @@ struct ScopeRouterFactory<Err: ErrorRenderer> {
case_insensitive: bool, case_insensitive: bool,
} }
impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ScopeRouterFactory<Err> { impl<Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>> for ScopeRouterFactory<Err> {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type InitError = (); type InitError = ();
@ -610,7 +610,7 @@ struct ScopeRouter<Err: ErrorRenderer> {
default: Option<HttpService<Err>>, default: Option<HttpService<Err>>,
} }
impl<Err: ErrorRenderer> Service<WebRequest<Err>> for ScopeRouter<Err> { impl<Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for ScopeRouter<Err> {
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type Future = Either<BoxResponse<Err>, Ready<Self::Response, Self::Error>>; type Future = Either<BoxResponse<Err>, Ready<Self::Response, Self::Error>>;
@ -620,7 +620,7 @@ impl<Err: ErrorRenderer> Service<WebRequest<Err>> for ScopeRouter<Err> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
fn call(&self, mut req: WebRequest<Err>) -> Self::Future { fn call(&self, mut req: &'a mut WebRequest<'a, Err>) -> Self::Future {
let res = self.router.recognize_checked(&mut req, |req, guards| { let res = self.router.recognize_checked(&mut req, |req, guards| {
if let Some(guards) = guards { if let Some(guards) = guards {
for f in guards { for f in guards {

View file

@ -1,7 +1,8 @@
use std::{marker::PhantomData, rc::Rc}; use std::task::{Context, Poll};
use std::{convert::Infallible, future::Future, marker::PhantomData, pin::Pin, rc::Rc};
use crate::router::{IntoPattern, ResourceDef}; use crate::router::{IntoPattern, ResourceDef};
use crate::service::{IntoServiceFactory, ServiceFactory}; use crate::service::{IntoServiceFactory, Service, ServiceFactory};
use crate::util::Extensions; use crate::util::Extensions;
use super::boxed::{self, BoxServiceFactory}; use super::boxed::{self, BoxServiceFactory};
@ -11,33 +12,31 @@ use super::rmap::ResourceMap;
use super::types::state::StateFactory; use super::types::state::StateFactory;
use super::{guard::Guard, ErrorRenderer, WebRequest, WebResponse}; use super::{guard::Guard, ErrorRenderer, WebRequest, WebResponse};
pub trait WebServiceFactory<'a, Err: ErrorRenderer> { pub trait WebService<'a, Err: ErrorRenderer>: 'static {
fn register(self, config: &mut WebServiceConfig<'a, Err>); fn register(self, config: &mut WebServiceConfig<'a, Err>);
} }
pub(super) trait AppServiceFactory<'a, Err: ErrorRenderer> { pub(super) trait WebServiceWrapper<'a, Err: ErrorRenderer> {
fn register(&mut self, config: &mut WebServiceConfig<'a, Err>); fn register(&mut self, config: &mut WebServiceConfig<'a, Err>);
} }
pub(super) struct ServiceFactoryWrapper<T> { pub(super) fn create_web_service<'a, T, Err>(svc: T) -> Box<dyn WebServiceWrapper<'a, Err>>
factory: Option<T>,
}
impl<T> ServiceFactoryWrapper<T> {
pub(super) fn new(factory: T) -> Self {
Self {
factory: Some(factory),
}
}
}
impl<'a, T, Err> AppServiceFactory<'a, Err> for ServiceFactoryWrapper<T>
where where
T: WebService<'a, Err> + 'static,
Err: ErrorRenderer,
{
Box::new(WebServiceWrapperInner(Some(svc)))
}
struct WebServiceWrapperInner<T>(Option<T>);
impl<'a, T, Err> WebServiceWrapper<'a, Err> for WebServiceWrapperInner<T>
where
T: WebService<'a, Err> + 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
T: WebServiceFactory<'a, Err>,
{ {
fn register(&mut self, config: &mut WebServiceConfig<'a, Err>) { fn register(&mut self, config: &mut WebServiceConfig<'a, Err>) {
if let Some(item) = self.factory.take() { if let Some(item) = self.0.take() {
item.register(config) item.register(config)
} }
} }
@ -131,7 +130,7 @@ impl<'a, Err: ErrorRenderer> WebServiceConfig<'a, Err> {
nested: Option<Rc<ResourceMap>>, nested: Option<Rc<ResourceMap>>,
) where ) where
S: ServiceFactory< S: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = WebResponse, Response = WebResponse,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
@ -209,9 +208,9 @@ impl WebServiceAdapter {
// /// Set a service factory implementation and generate web service. // /// Set a service factory implementation and generate web service.
// pub fn finish<'a, T, F, Err>(self, service: F) -> impl WebServiceFactory<'a, Err> // pub fn finish<'a, T, F, Err>(self, service: F) -> impl WebServiceFactory<'a, Err>
// where // where
// F: IntoServiceFactory<T, &'a mut WebRequest<Err>>, // F: IntoServiceFactory<T, &'a mut WebRequest<'a, Err>>,
// T: ServiceFactory< // T: ServiceFactory<
// &'a mut WebRequest<Err>, // &'a mut WebRequest<'a, Err>,
// Response = WebResponse, // Response = WebResponse,
// Error = Err::Container, // Error = Err::Container,
// InitError = (), // InitError = (),
@ -228,62 +227,62 @@ impl WebServiceAdapter {
// } // }
} }
struct WebServiceImpl<T> { // struct WebServiceImpl<T> {
srv: T, // srv: T,
rdef: Vec<String>, // rdef: Vec<String>,
name: Option<String>, // name: Option<String>,
guards: Vec<Box<dyn Guard>>, // guards: Vec<Box<dyn Guard>>,
} // }
impl<'a, T, Err> WebServiceFactory<'a, Err> for WebServiceImpl<T> // impl<'a, T, Err> WebServiceFactory<'a, Err> for WebServiceImpl<T>
where // where
T: ServiceFactory< // T: ServiceFactory<
&'a mut WebRequest<Err>, // &'a mut WebRequest<'a, Err>,
Response = WebResponse, // Response = WebResponse,
Error = Err::Container, // Error = Err::Container,
InitError = (), // InitError = (),
> + 'static, // > + 'static,
T::Future: 'static, // T::Future: 'static,
T::Service: 'static, // T::Service: 'static,
Err: ErrorRenderer, // Err: ErrorRenderer,
{ // {
fn register(mut self, config: &mut WebServiceConfig<'a, Err>) { // fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
let guards = if self.guards.is_empty() { // let guards = if self.guards.is_empty() {
None // None
} else { // } else {
Some(std::mem::take(&mut self.guards)) // Some(std::mem::take(&mut self.guards))
}; // };
let mut rdef = if config.is_root() || !self.rdef.is_empty() { // let mut rdef = if config.is_root() || !self.rdef.is_empty() {
ResourceDef::new(insert_slash(self.rdef)) // ResourceDef::new(insert_slash(self.rdef))
} else { // } else {
ResourceDef::new(self.rdef) // ResourceDef::new(self.rdef)
}; // };
if let Some(ref name) = self.name { // if let Some(ref name) = self.name {
*rdef.name_mut() = name.clone(); // *rdef.name_mut() = name.clone();
} // }
config.register_service(rdef, guards, self.srv, None) // config.register_service(rdef, guards, self.srv, None)
} // }
} // }
/// WebServiceFactory implementation for a Vec<T> // /// WebServiceFactory implementation for a Vec<T>
#[allow(unused_parens)] // #[allow(unused_parens)]
impl<'a, Err, T> WebServiceFactory<'a, Err> for Vec<T> // impl<'a, Err, T> WebServiceFactory<'a, Err> for Vec<T>
where // where
Err: ErrorRenderer, // Err: ErrorRenderer,
T: WebServiceFactory<'a, Err> + 'static, // T: WebServiceFactory<'a, Err> + 'static,
{ // {
fn register(mut self, config: &mut WebServiceConfig<'a, Err>) { // fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
for service in self.drain(..) { // for service in self.drain(..) {
service.register(config); // service.register(config);
} // }
} // }
} // }
macro_rules! tuple_web_service({$(($n:tt, $T:ident)),+} => { macro_rules! tuple_web_service({$(($n:tt, $T:ident)),+} => {
/// WebServiceFactory implementation for a tuple /// WebServiceFactory implementation for a tuple
#[allow(unused_parens)] #[allow(unused_parens)]
impl<'a, Err: ErrorRenderer, $($T: WebServiceFactory<'a, Err> + 'static),+> WebServiceFactory<'a, Err> for ($($T,)+) { impl<'a, Err: ErrorRenderer, $($T: WebService<'a, Err> + 'static),+> WebService<'a, Err> for ($($T,)+) {
fn register(self, config: &mut WebServiceConfig<'a, Err>) { fn register(self, config: &mut WebServiceConfig<'a, Err>) {
$( $(
self.$n.register(config); self.$n.register(config);
@ -295,10 +294,10 @@ macro_rules! tuple_web_service({$(($n:tt, $T:ident)),+} => {
macro_rules! array_web_service({$num:tt, $($T:ident),+} => { macro_rules! array_web_service({$num:tt, $($T:ident),+} => {
/// WebServiceFactory implementation for an array /// WebServiceFactory implementation for an array
#[allow(unused_parens)] #[allow(unused_parens)]
impl<'a, Err, T> WebServiceFactory<'a, Err> for [T; $num] impl<'a, Err, T> WebService<'a, Err> for [T; $num]
where where
Err: ErrorRenderer, Err: ErrorRenderer,
T: WebServiceFactory<'a, Err> + 'static, T: WebService<'a, Err> + 'static,
{ {
fn register(self, config: &mut WebServiceConfig<'a, Err>) { fn register(self, config: &mut WebServiceConfig<'a, Err>) {
let [$($T,)+] = self; let [$($T,)+] = self;
@ -315,45 +314,45 @@ macro_rules! array_web_service({$num:tt, $($T:ident),+} => {
mod m { mod m {
use super::*; use super::*;
array_web_service!(1,A); array_web_service!(1,A);
array_web_service!(2,A,B); array_web_service!(2,A,B);
array_web_service!(3,A,B,C); array_web_service!(3,A,B,C);
array_web_service!(4,A,B,C,D); array_web_service!(4,A,B,C,D);
array_web_service!(5,A,B,C,D,E); array_web_service!(5,A,B,C,D,E);
array_web_service!(6,A,B,C,D,E,F); array_web_service!(6,A,B,C,D,E,F);
array_web_service!(7,A,B,C,D,E,F,G); array_web_service!(7,A,B,C,D,E,F,G);
array_web_service!(8,A,B,C,D,E,F,G,H); array_web_service!(8,A,B,C,D,E,F,G,H);
array_web_service!(9,A,B,C,D,E,F,G,H,I); array_web_service!(9,A,B,C,D,E,F,G,H,I);
array_web_service!(10,A,B,C,D,E,F,G,H,I,J); array_web_service!(10,A,B,C,D,E,F,G,H,I,J);
array_web_service!(11,A,B,C,D,E,F,G,H,I,J,K); array_web_service!(11,A,B,C,D,E,F,G,H,I,J,K);
array_web_service!(12,A,B,C,D,E,F,G,H,I,J,K,L); array_web_service!(12,A,B,C,D,E,F,G,H,I,J,K,L);
array_web_service!(13,A,B,C,D,E,F,G,H,I,J,K,L,M); array_web_service!(13,A,B,C,D,E,F,G,H,I,J,K,L,M);
array_web_service!(14,A,B,C,D,E,F,G,H,I,J,K,L,M,N); array_web_service!(14,A,B,C,D,E,F,G,H,I,J,K,L,M,N);
array_web_service!(15,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O); array_web_service!(15,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O);
array_web_service!(16,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P); array_web_service!(16,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P);
tuple_web_service!((0,A)); tuple_web_service!((0,A));
tuple_web_service!((0,A),(1,B)); tuple_web_service!((0,A),(1,B));
tuple_web_service!((0,A),(1,B),(2,C)); tuple_web_service!((0,A),(1,B),(2,C));
tuple_web_service!((0,A),(1,B),(2,C),(3,D)); tuple_web_service!((0,A),(1,B),(2,C),(3,D));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S),(19,T)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S),(19,T));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S),(19,T),(20,V)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S),(19,T),(20,V));
tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S),(19,T),(20,V),(21,X)); tuple_web_service!((0,A),(1,B),(2,C),(3,D),(4,E),(5,F),(6,G),(7,H),(8,I),(9,J),(10,K),(11,L),(12,M),(13,N),(14,O),(15,P),(16,Q),(17,R),(18,S),(19,T),(20,V),(21,X));
} }
#[cfg(test)] #[cfg(test)]

View file

@ -9,32 +9,24 @@ use crate::service::{
}; };
use crate::util::{ready, Ready}; use crate::util::{ready, Ready};
use super::httprequest::{HttpRequest, WeakHttpRequest}; use super::httprequest::HttpRequest;
use super::{ErrorContainer, ErrorRenderer, WebRequest, WebResponse}; use super::{ErrorContainer, ErrorRenderer, WebRequest, WebResponse};
pub struct Stack<Inner, Outer, Err> { pub struct Stack<Inner, Outer> {
inner: Inner, inner: Inner,
outer: Outer, outer: Outer,
_t: PhantomData<Err>,
} }
impl<Inner, Outer, Err> Stack<Inner, Outer, Err> { impl<Inner, Outer> Stack<Inner, Outer> {
pub(super) fn new(inner: Inner, outer: Outer) -> Self { pub(super) fn new(inner: Inner, outer: Outer) -> Self {
Stack { Stack { inner, outer }
inner,
outer,
_t: PhantomData,
}
} }
} }
impl<S, Inner, Outer, Err> Transform<S> for Stack<Inner, Outer, Err> impl<S, Inner, Outer> Transform<S> for Stack<Inner, Outer>
where where
Err: ErrorRenderer,
Inner: Transform<S>, Inner: Transform<S>,
Inner::Service: Service<WebRequest<Err>, Response = WebResponse>, Outer: Transform<Next<Inner::Service>>,
<Inner::Service as Service<WebRequest<Err>>>::Error: Into<Err::Container>,
Outer: Transform<Next<Inner::Service, Err>>,
{ {
type Service = Outer::Service; type Service = Outer::Service;
@ -77,9 +69,9 @@ pub struct Middleware<S, Err> {
_t: PhantomData<Err>, _t: PhantomData<Err>,
} }
impl<'a, S, Err> Service<&'a mut WebRequest<Err>> for Middleware<S, Err> impl<'a, S, Err> Service<&'a mut WebRequest<'a, Err>> for Middleware<S, Err>
where where
S: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, S: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
type Response = WebResponse; type Response = WebResponse;
@ -93,7 +85,7 @@ where
} }
#[inline] #[inline]
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
MiddlewareResponse { MiddlewareResponse {
fut: self.md.call(req), fut: self.md.call(req),
} }
@ -101,7 +93,7 @@ where
} }
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
pub struct MiddlewareResponse<'a, S: Service<&'a mut WebRequest<Err>>, Err> { pub struct MiddlewareResponse<'a, S: Service<&'a mut WebRequest<'a, Err>>, Err> {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
} }
@ -109,7 +101,7 @@ pin_project_lite::pin_project! {
impl<'a, S, Err> Future for MiddlewareResponse<'a, S, Err> impl<'a, S, Err> Future for MiddlewareResponse<'a, S, Err>
where where
S: Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>, S: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
type Output = Result<WebResponse, Err::Container>; type Output = Result<WebResponse, Err::Container>;
@ -119,23 +111,19 @@ where
} }
} }
pub struct Next<S, Err> { pub struct Next<S> {
inner: Rc<S>, next: S,
_t: PhantomData<Err>,
} }
impl<S, Err> Next<S, Err> { impl<S> Next<S> {
pub(super) fn new(inner: S) -> Self { pub(super) fn new(next: S) -> Self {
Next { Next { next }
inner: Rc::new(inner),
_t: PhantomData,
}
} }
} }
impl<'a, S, Err> Service<&'a mut WebRequest<Err>> for Next<S, Err> impl<'a, S, Err> Service<&'a mut WebRequest<'a, Err>> for Next<S>
where where
S: Service<&'a mut WebRequest<Err>, Response = WebResponse> + 'static, S: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse> + 'static,
S::Error: Into<Err::Container> + 'static, S::Error: Into<Err::Container> + 'static,
S::Future: 'a, S::Future: 'a,
Err: ErrorRenderer, Err: ErrorRenderer,
@ -146,16 +134,17 @@ where
#[inline] #[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let _ = ready!(self.inner.poll_ready(cx)); let _ = ready!(self.next.poll_ready(cx));
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
#[inline] #[inline]
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
let next = self.inner.clone(); let r = unsafe { (req as *mut WebRequest<'a, Err>).as_mut().unwrap() };
let fut = self.next.call(r);
Box::pin(async move { Box::pin(async move {
let result = next.call(req).await; match fut.await {
match result {
Ok(res) => Ok(res), Ok(res) => Ok(res),
Err(err) => Ok(WebResponse::new(err.into().error_response(&req.req))), Err(err) => Ok(WebResponse::new(err.into().error_response(&req.req))),
} }
@ -164,16 +153,16 @@ where
} }
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
pub struct NextResponse<'a, S: Service<&'a mut WebRequest<Err>>, Err> { pub struct NextResponse<'a, S: Service<&'a mut WebRequest<'a, Err>>, Err> {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
req: &'a mut WebRequest<Err>, req: &'a mut WebRequest<'a, Err>,
} }
} }
impl<'a, S, Err> Future for NextResponse<'a, S, Err> impl<'a, S, Err> Future for NextResponse<'a, S, Err>
where where
S: Service<&'a mut WebRequest<Err>, Response = WebResponse>, S: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse>,
S::Error: Into<Err::Container>, S::Error: Into<Err::Container>,
Err: ErrorRenderer, Err: ErrorRenderer,
{ {
@ -191,37 +180,31 @@ where
} }
} }
pub struct Filter<Err>(PhantomData<Err>); pub struct Filter;
impl<Err: ErrorRenderer> Filter<Err> { impl<'a, Err: ErrorRenderer> FiltersFactory<'a, Err> for Filter {
pub(super) fn new() -> Self { type Service = Filter;
Filter(PhantomData)
}
}
impl<'a, Err: ErrorRenderer> FiltersFactory<'a, Err> for Filter<Err> {
type Service = Filter<Err>;
fn create(self) -> Self::Service { fn create(self) -> Self::Service {
self self
} }
} }
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<Err>> for Filter<Err> { impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>> for Filter {
type Response = &'a mut WebRequest<Err>; type Response = &'a mut WebRequest<'a, Err>;
type Error = Err::Container; type Error = Err::Container;
type InitError = (); type InitError = ();
type Service = Filter<Err>; type Service = Filter;
type Future = Ready<Filter<Err>, ()>; type Future = Ready<Filter, ()>;
#[inline] #[inline]
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
Ready::Ok(Filter(PhantomData)) Ready::Ok(Filter)
} }
} }
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for Filter<Err> { impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for Filter {
type Response = &'a mut WebRequest<Err>; type Response = &'a mut WebRequest<'a, Err>;
type Error = Err::Container; type Error = Err::Container;
type Future = Ready<Self::Response, Self::Error>; type Future = Ready<Self::Response, Self::Error>;
@ -231,33 +214,28 @@ impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for Filter<Err> {
} }
#[inline] #[inline]
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future { fn call(&self, req: &'a mut WebRequest<'a, Err>) -> Self::Future {
Ready::Ok(req) Ready::Ok(req)
} }
} }
pub struct Filters<First, Second, Err> { pub struct Filters<First, Second> {
first: First, first: First,
second: Second, second: Second,
_t: PhantomData<Err>,
} }
impl<First, Second, Err> Filters<First, Second, Err> { impl<First, Second> Filters<First, Second> {
pub(super) fn new(first: First, second: Second) -> Self { pub(super) fn new(first: First, second: Second) -> Self {
Filters { Filters { first, second }
first,
second,
_t: PhantomData,
}
} }
} }
impl<'a, First, Second, Err> FiltersFactory<'a, Err> for Filters<First, Second, Err> impl<'a, First, Second, Err> FiltersFactory<'a, Err> for Filters<First, Second>
where where
Err: ErrorRenderer, Err: ErrorRenderer,
First: ServiceFactory< First: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static, > + 'static,
@ -265,13 +243,13 @@ where
First::Future: 'static, First::Future: 'static,
Second: FiltersFactory<'a, Err>, Second: FiltersFactory<'a, Err>,
Second::Service: ServiceFactory< Second::Service: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
>, >,
<Second::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service: 'static, <Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
<Second::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Future: 'static, <Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
{ {
type Service = AndThenFactory<First, Second::Service>; type Service = AndThenFactory<First, Second::Service>;
@ -282,8 +260,8 @@ where
pub trait FiltersFactory<'a, Err: ErrorRenderer> { pub trait FiltersFactory<'a, Err: ErrorRenderer> {
type Service: ServiceFactory< type Service: ServiceFactory<
&'a mut WebRequest<Err>, &'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<Err>, Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container, Error = Err::Container,
InitError = (), InitError = (),
> + 'static; > + 'static;

View file

@ -31,7 +31,7 @@ use crate::web::{FromRequest, HttpResponse, Responder, WebRequest, WebResponse};
/// Create service that always responds with `HttpResponse::Ok()` /// Create service that always responds with `HttpResponse::Ok()`
pub fn ok_service<Err: ErrorRenderer>( pub fn ok_service<Err: ErrorRenderer>(
) -> impl Service<WebRequest<Err>, Response = WebResponse, Error = std::convert::Infallible> ) -> impl Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = std::convert::Infallible>
{ {
default_service::<Err>(StatusCode::OK) default_service::<Err>(StatusCode::OK)
} }
@ -39,9 +39,9 @@ pub fn ok_service<Err: ErrorRenderer>(
/// Create service that responds with response with specified status code /// Create service that responds with response with specified status code
pub fn default_service<Err: ErrorRenderer>( pub fn default_service<Err: ErrorRenderer>(
status_code: StatusCode, status_code: StatusCode,
) -> impl Service<WebRequest<Err>, Response = WebResponse, Error = std::convert::Infallible> ) -> impl Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = std::convert::Infallible>
{ {
(move |req: WebRequest<Err>| { (move |req: &'a mut WebRequest<'a, Err>| {
Ready::Ok(req.into_response(HttpResponse::build(status_code).finish())) Ready::Ok(req.into_response(HttpResponse::build(status_code).finish()))
}) })
.into_service() .into_service()
@ -248,13 +248,13 @@ where
.unwrap_or_else(|_| panic!("read_response_json failed during deserialization")) .unwrap_or_else(|_| panic!("read_response_json failed during deserialization"))
} }
// /// Helper method for extractors testing /// Helper method for extractors testing
// pub async fn from_request<'a, T: FromRequest<'a, DefaultError>>( pub async fn from_request<T: FromRequest<DefaultError>>(
// req: &'a HttpRequest, req: &HttpRequest,
// payload: &'a mut Payload, payload: &mut Payload,
// ) -> Result<T, T::Error> { ) -> Result<T, T::Error> {
// T::from_request(req, payload).await T::from_request(req, payload).await
// } }
/// Helper method for responders testing /// Helper method for responders testing
pub async fn respond_to<T: Responder<DefaultError>>( pub async fn respond_to<T: Responder<DefaultError>>(