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)]
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
let __resource = ntex::web::Resource::new(#path)
@ -162,7 +162,7 @@ impl Route {
#(.guard(ntex::web::guard::fn_guard(#extra_guards)))*
.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
/// 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
Self: Sized,
F: Fn(Self::Error) -> E,
@ -185,23 +185,17 @@ pub trait ServiceFactory<Req, Cfg = ()> {
#[inline]
/// Map this service's error to a different error, returning a new service.
fn map_err<F, E>(
self,
f: F,
) -> crate::map_err::MapErrServiceFactory<Self, Req, Cfg, F, E>
fn map_err<F, E>(self, f: F) -> crate::map_err::MapErrServiceFactory<Self, Cfg, F, E>
where
Self: Sized,
F: Fn(Self::Error) -> E + Clone,
{
crate::map_err::MapErrServiceFactory::<_, _, Cfg, _, _>::new(self, f)
crate::map_err::MapErrServiceFactory::new(self, f)
}
#[inline]
/// Map this factory's init error to a different error, returning a new service.
fn map_init_err<F, E>(
self,
f: F,
) -> crate::map_init_err::MapInitErr<Self, Req, Cfg, F, E>
fn map_init_err<F, E>(self, f: F) -> crate::map_init_err::MapInitErr<Self, F, E>
where
Self: Sized,
F: Fn(Self::InitError) -> E + Clone,

View file

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

View file

@ -7,106 +7,198 @@ use crate::router::{Path, ResourceDef, Router};
use crate::service::{
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::config::AppConfig;
use super::guard::Guard;
use super::httprequest::{HttpRequest, HttpRequestPool};
use super::rmap::ResourceMap;
use super::service::{AppServiceFactory, WebServiceConfig};
use super::stack::Next;
use super::service::{WebService, WebServiceConfig, WebServiceWrapper};
use super::stack::{Filter, FiltersFactory, Next};
use super::types::state::StateFactory;
use super::{ErrorRenderer, WebRequest, WebResponse};
use super::{ErrorContainer, ErrorRenderer, WebRequest, WebResponse};
type Guards = Vec<Box<dyn Guard>>;
type BoxResponse<'a, Err: ErrorRenderer> =
Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'a>>;
type BoxResponse<'a> = Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>> + 'a>>;
type FnStateFactory =
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.
pub struct AppFactory<'a, T, F, Err: ErrorRenderer>
where
F: ServiceFactory<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
Error = Err::Container,
InitError = (),
> + 'static,
Err: ErrorRenderer,
{
pub(super) middleware: Rc<T>,
pub(super) filter: PipelineFactory<F, &'a mut WebRequest<Err>>,
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 AppServiceFactory<'a, Err>>>>>,
pub(super) default: Option<Rc<BoxServiceFactory<'a, Err>>>,
pub(super) external: RefCell<Vec<ResourceDef>>,
pub(super) case_insensitive: bool,
pub struct AppFactory(WebAppFactory);
pub struct AppService(WebAppHandler);
type WebAppFactory =
Box<dyn Fn(AppConfig) -> Pin<Box<dyn Future<Output = Result<AppService, ()>>>>>;
type WebAppHandler =
Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>>>>>;
type WebAppHandler2<'a> = Box<
dyn Fn(Request) -> Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>> + 'a>>
+ 'a,
>;
impl AppFactory {
pub(super) fn new<'a, M, F, Err: ErrorRenderer>(
app: AppFactoryInner<'a, M, F, Err>,
) -> Self
where
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>
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,
{
impl ServiceFactory<Request> for AppFactory {
type Response = WebResponse;
type Error = Err::Container;
type Error = Infallible;
type InitError = ();
type Service = AppFactoryService<'a, T::Service, Err>;
type Future =
Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>> + 'a>>;
type Service = AppService;
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
fn new_service(&self, _: ()) -> Self::Future {
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
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,
M: Transform<
AppRouting<
'a,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err,
>,
>,
M::Service:
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,
{
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 Error = Err::Container;
type InitError = ();
type Service = AppFactoryService<'a, T::Service, Err>;
type Future =
Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>> + 'a>>;
type Service = Self;
type Future = Ready<Self::Service, Self::InitError>;
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
let default = self.default.clone().unwrap_or_else(|| panic!());
// .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)
// }
// }
// )))
// });
let default = Rc::new(self.default.take().unwrap());
// App config
let mut config = WebServiceConfig::new(config, default.clone(), self.state.clone());
@ -142,7 +234,7 @@ where
let rmap = Rc::new(rmap);
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_factories = self.state_factories.clone();
let mut extensions = self
@ -152,251 +244,150 @@ where
.unwrap_or_else(Extensions::new);
let middleware = self.middleware.clone();
Box::pin(async move {
// create http services
for (path, factory, guards) in &mut services.iter() {
let service = factory.new_service(()).await?;
router.rdef(path.clone(), service).2 = guards.borrow_mut().take();
}
let f: Pin<Box<dyn Future<Output = Result<WebAppHandler, ()>> + 'a>> =
Box::pin(async move {
// create http services
for (path, factory, guards) in &mut services.iter() {
let service = factory.new_service(()).await?;
router.rdef(path.clone(), service).2 = guards.borrow_mut().take();
}
let routing = AppRouting {
router: router.finish(),
default: Some(default_fut.await?),
};
// router
let routing = AppRouting {
filter: filter_fut.await?,
router: Rc::new(AppRouter {
router: router.finish(),
default: Some(default_fut.await?),
}),
};
// main service
let service = AppService {
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 {
// create app state container
for f in state.iter() {
f.create(&mut extensions);
}
}
Ok(AppFactoryService {
rmap,
config,
service: middleware.new_transform(Next::new(service)),
state: Rc::new(extensions),
pool: HttpRequestPool::create(),
_t: PhantomData,
})
})
// async state factories
for fut in state_factories.iter() {
if let Ok(f) = fut().await {
f.create(&mut extensions);
}
}
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 AppFactoryService<'a, T, Err>
where
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>,
pub struct AppRouting<'a, F, Err: ErrorRenderer> {
filter: F,
router: Rc<AppRouter<'a, Err>>,
}
impl<'a, T, Err> Service<Request> for AppFactoryService<'a, T, Err>
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> {
struct AppRouter<'a, Err: ErrorRenderer> {
router: Router<BoxService<'a, Err>, Guards>,
default: Option<BoxService<'a, Err>>,
}
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<Err>> for AppRouting<'a, Err> {
type Response = WebResponse;
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>
impl<'a, F, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>>
for AppRouting<'a, F, Err>
where
F: Service<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
>,
F::Future: 'a,
Err: ErrorRenderer,
{
type Response = WebResponse;
type Error = Err::Container;
type Future = AppServiceResponse<'a, F, Err>;
type Error = Infallible;
type Future = BoxResponse<'a>;
#[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let ready1 = self.filter.poll_ready(cx)?.is_ready();
let ready2 = self.routing.poll_ready(cx)?.is_ready();
if ready1 && ready2 {
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
let _ = ready!(self.filter.poll_ready(cx));
Poll::Ready(Ok(()))
}
fn call(&self, req: &'a mut WebRequest<Err>) -> Self::Future {
AppServiceResponse {
filter: self.filter.call(req),
routing: self.routing.clone(),
endpoint: None,
}
}
}
fn call(&self, mut req: &'a mut WebRequest<'a, Err>) -> Self::Future {
let r1 = unsafe { (req as *mut WebRequest<'a, Err>).as_mut().unwrap() };
let r2 = unsafe { (req as *mut WebRequest<'a, Err>).as_mut().unwrap() };
pin_project_lite::pin_project! {
pub struct AppServiceResponse<'a, F: Service<&'a mut WebRequest<Err>>, Err: ErrorRenderer> {
#[pin]
filter: F::Future,
routing: Rc<AppRouting<'a, Err>>,
endpoint: Option<BoxResponse<'a, Err>>,
}
}
let fut = self.filter.call(r1);
let router = self.router.clone();
impl<'a, F, Err> Future for AppServiceResponse<'a, F, Err>
where
F: Service<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
Error = Err::Container,
>,
Err: ErrorRenderer,
{
type Output = Result<WebResponse, Err::Container>;
Box::pin(async move {
match fut.await {
Ok(res) => (),
Err(err) => return Ok(WebResponse::new(err.error_response(&req.req))),
}
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.as_mut().project();
let res = router.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(fut) = this.endpoint.as_mut() {
Pin::new(fut).poll(cx)
} else {
let res = if let Poll::Ready(res) = this.filter.poll(cx) {
res?
if let Some((srv, _info)) = res {
match srv.call(r2).await {
Ok(res) => Ok(res),
Err(err) => Ok(WebResponse::new(err.error_response(&req.req))),
}
} 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 {
return Poll::Pending;
};
*this.endpoint = Some(this.routing.call(res));
self.poll(cx)
}
Ok(WebResponse::new(Response::NotFound().finish()))
}
})
}
}

View file

@ -13,7 +13,7 @@ pub type BoxFactoryFuture<'a, Err: ErrorRenderer> =
pub type BoxService<'a, Err: ErrorRenderer> = Box<
dyn Service<
&'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Err::Container,
Future = BoxFuture<'a, Err>,
@ -27,21 +27,21 @@ pub fn factory<'a, T, Err>(factory: T) -> BoxServiceFactory<'a, Err>
where
Err: ErrorRenderer,
T: ServiceFactory<
&'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Err::Container,
InitError = (),
> + 'static,
T::Future: '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))
}
type Inner<'a, Err: ErrorRenderer + 'static> = Box<
dyn ServiceFactory<
&'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Err::Container,
InitError = (),
@ -50,7 +50,7 @@ type Inner<'a, Err: ErrorRenderer + 'static> = Box<
> + 'static,
>;
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<Err>>
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>>
for BoxServiceFactory<'a, Err>
{
type Response = WebResponse;
@ -73,14 +73,14 @@ impl<'a, T, Err> FactoryWrapper<T, Err>
where
Err: ErrorRenderer + 'static,
T: ServiceFactory<
&'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Err::Container,
InitError = (),
> + 'static,
T::Future: '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> {
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
Err: ErrorRenderer + 'static,
T: ServiceFactory<
&'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Err::Container,
InitError = (),
> + 'static,
T::Future: '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 Error = Err::Container;
@ -123,7 +123,7 @@ struct ServiceWrapper<T, Err>(T, PhantomData<Err>);
impl<'a, T, Err> ServiceWrapper<T, Err>
where
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,
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
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,
T::Future: 'a,
{
@ -154,7 +154,7 @@ where
}
#[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))
}
}

View file

@ -4,7 +4,7 @@ use crate::router::ResourceDef;
use super::resource::Resource;
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::{DefaultError, ErrorRenderer};
@ -60,7 +60,7 @@ impl Default for AppConfig {
/// to set of external methods. This could help with
/// modularization of big application configuration.
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) external: Vec<ResourceDef>,
}
@ -100,10 +100,9 @@ impl<'a, Err: ErrorRenderer> ServiceConfig<'a, Err> {
/// This is same as `App::service()` method.
pub fn service<F>(&mut self, factory: F) -> &mut Self
where
F: WebServiceFactory<'a, Err> + 'static,
F: WebService<'a, Err> + 'static,
{
self.services
.push(Box::new(ServiceFactoryWrapper::new(factory)));
self.services.push(create_web_service(factory));
self
}
@ -136,7 +135,7 @@ mod tests {
#[crate::rt_test]
async fn test_configure_state() {
let cfg = |cfg: &mut ServiceConfig<_>| {
let cfg = |cfg: &mut ServiceConfig<'_, _>| {
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.
///
/// 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.
type Error;
/// 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
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
///
/// 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)
}
}
@ -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
T: FromRequest<Err> + 'static,
T: FromRequest<'a, Err> + 'static,
T::Future: 'static,
Err: ErrorRenderer,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
<T as FromRequest<'a, Err>>::Error: Into<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]
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);
Box::pin(async move {
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
T: FromRequest<E> + 'static,
T::Error: 'static,
T::Future: 'static,
T: FromRequest<'a, E> + 'static,
E: ErrorRenderer,
{
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]
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);
Box::pin(async move {
match fut.await {
@ -162,7 +161,7 @@ where
}
#[doc(hidden)]
impl<E: ErrorRenderer> FromRequest<E> for () {
impl<'a, E: ErrorRenderer> FromRequest<'a, E> for () {
type Error = 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
#[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
$(<$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 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 {
items: <($(Option<$T>,)+)>::default(),
$($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! {
#[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>,)+),
$(#[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
$(<$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>;

View file

@ -38,7 +38,7 @@ where
pub(super) trait HandlerFn<Err: ErrorRenderer> {
fn call<'b>(
&self,
_: &'b mut WebRequest<Err>,
_: &'b mut WebRequest<'b, Err>,
) -> Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'b>>;
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
F: Handler<T, Err>,
T: FromRequest<Err> + 'static,
T: FromRequest<'a, Err> + 'static,
T::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
fn call<'b>(
&self,
req: &'b mut WebRequest<Err>,
req: &'b mut WebRequest<'b, Err>,
) -> Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>> + 'b>> {
let mut pl = Rc::get_mut(&mut (req.req).0).unwrap().payload.take();
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::{
HeaderMap, HttpMessage, Message, Method, Payload, RequestHead, Uri, Version,
@ -17,8 +17,6 @@ use super::rmap::ResourceMap;
/// An HTTP Request
pub struct HttpRequest(pub(crate) Rc<HttpRequestInner>);
pub(super) struct WeakHttpRequest(pub(super) Weak<HttpRequestInner>);
pub(crate) struct HttpRequestInner {
pub(crate) head: Message<RequestHead>,
pub(crate) path: Path<Uri>,
@ -50,10 +48,6 @@ impl HttpRequest {
pool,
}))
}
pub(super) fn downgrade(&self) -> WeakHttpRequest {
WeakHttpRequest(Rc::downgrade(&self.0))
}
}
impl HttpRequest {

View file

@ -59,14 +59,14 @@ pub struct CompressMiddleware<S> {
encoding: ContentEncoding,
}
impl<S, E> Service<WebRequest<E>> for CompressMiddleware<S>
impl<'a, S, E> Service<WebRequest<E>> for CompressMiddleware<S>
where
S: Service<WebRequest<E>, Response = WebResponse>,
E: ErrorRenderer,
{
type Response = WebResponse;
type Error = S::Error;
type Future = CompressResponse<S, E>;
type Future = CompressResponse<'a, S, E>;
#[inline]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
@ -100,7 +100,7 @@ where
pin_project_lite::pin_project! {
#[doc(hidden)]
pub struct CompressResponse<S: Service<WebRequest<E>>, E>
pub struct CompressResponse<'a, S: Service<WebRequest<E>>, E>
{
#[pin]
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
S: Service<WebRequest<E>, Response = WebResponse>,
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::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
use crate::service::{Service, Transform};
use crate::web::{WebRequest, WebResponse};
use crate::web::{WebRequest, WebResponse, ErrorRenderer};
/// `Middleware` for setting default response headers.
///
@ -102,14 +102,15 @@ pub struct DefaultHeadersMiddleware<S> {
inner: Rc<Inner>,
}
impl<S, E> Service<WebRequest<E>> for DefaultHeadersMiddleware<S>
impl<'a, S, E> Service<WebRequest<E>> for DefaultHeadersMiddleware<S>
where
S: Service<WebRequest<E>, Response = WebResponse, Error = Infallible>,
S::Future: 'static,
E: ErrorRenderer,
{
type Response = WebResponse;
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]
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {

View file

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

View file

@ -79,7 +79,7 @@ pub mod guard;
mod handler;
mod httprequest;
mod info;
pub mod middleware;
//pub mod middleware;
mod request;
mod resource;
mod responder;
@ -91,7 +91,7 @@ mod boxed;
mod server;
mod service;
mod stack;
pub mod test;
//pub mod test;
pub mod types;
mod util;
pub mod ws;
@ -125,7 +125,7 @@ pub use self::response::WebResponse;
pub use self::route::Route;
// pub use self::scope::Scope;
pub use self::server::HttpServer;
pub use self::service::WebServiceFactory;
pub use self::service::{WebService, WebServiceConfig};
pub use self::util::*;
pub mod dev {
@ -139,7 +139,7 @@ pub mod dev {
pub use crate::web::info::ConnectionInfo;
pub use crate::web::rmap::ResourceMap;
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(crate) fn insert_slash(mut patterns: Vec<String>) -> Vec<String> {
@ -151,55 +151,55 @@ pub mod dev {
patterns
}
// #[doc(hidden)]
// #[inline(always)]
// pub fn __assert_extractor<'a, Err, T>()
// where
// T: super::FromRequest<'a, Err>,
// Err: super::ErrorRenderer,
// <T as super::FromRequest<'a, Err>>::Error: Into<Err::Container>,
// {
// }
#[doc(hidden)]
#[inline(always)]
pub fn __assert_extractor<'a, Err, T>()
where
T: super::FromRequest<'a, Err>,
Err: super::ErrorRenderer,
<T as super::FromRequest<'a, Err>>::Error: Into<Err::Container>,
{
}
// #[doc(hidden)]
// #[inline(always)]
// pub fn __assert_handler<Err, Fun, Fut>(
// f: Fun,
// ) -> impl Handler<(), Err, Future = Fut, Output = Fut::Output>
// where
// Err: super::ErrorRenderer,
// Fun: Fn() -> Fut + Clone + 'static,
// Fut: std::future::Future + 'static,
// Fut::Output: super::Responder<Err>,
// {
// f
// }
#[doc(hidden)]
#[inline(always)]
pub fn __assert_handler<Err, Fun, Fut>(
f: Fun,
) -> impl Handler<(), Err, Future = Fut, Output = Fut::Output>
where
Err: super::ErrorRenderer,
Fun: Fn() -> Fut + Clone + 'static,
Fut: std::future::Future + 'static,
Fut::Output: super::Responder<Err>,
{
f
}
// macro_rules! assert_handler ({ $name:ident, $($T:ident),+} => {
// #[doc(hidden)]
// #[inline(always)]
// pub fn $name<'a, Err, Fun, Fut, $($T,)+>(
// f: Fun,
// ) -> impl Handler<($($T,)+), Err, Future = Fut, Output = Fut::Output>
// where
// Err: $crate::web::ErrorRenderer,
// Fun: Fn($($T,)+) -> Fut + Clone + 'static,
// Fut: std::future::Future + 'static,
// Fut::Output: $crate::web::Responder<Err>,
// $($T: $crate::web::FromRequest<'a, Err>),+,
// {
// f
// }
// });
macro_rules! assert_handler ({ $name:ident, $($T:ident),+} => {
#[doc(hidden)]
#[inline(always)]
pub fn $name<'a, Err, Fun, Fut, $($T,)+>(
f: Fun,
) -> impl Handler<($($T,)+), Err, Future = Fut, Output = Fut::Output>
where
Err: $crate::web::ErrorRenderer,
Fun: Fn($($T,)+) -> Fut + Clone + 'static,
Fut: std::future::Future + 'static,
Fut::Output: $crate::web::Responder<Err>,
$($T: $crate::web::FromRequest<'a, Err>),+,
{
f
}
});
// assert_handler!(__assert_handler1, A);
// assert_handler!(__assert_handler2, A, B);
// assert_handler!(__assert_handler3, A, B, C);
// assert_handler!(__assert_handler4, A, B, C, D);
// assert_handler!(__assert_handler5, A, B, C, D, E);
// assert_handler!(__assert_handler6, A, B, C, D, E, F);
// 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_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_handler1, A);
assert_handler!(__assert_handler2, A, B);
assert_handler!(__assert_handler3, A, B, C);
assert_handler!(__assert_handler4, A, B, C, D);
assert_handler!(__assert_handler5, A, B, C, D, E);
assert_handler!(__assert_handler6, A, B, C, D, E, F);
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_handler9, A, B, C, D, E, F, G, H, I);
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::error::{ErrorRenderer, WebResponseError};
use super::httprequest::{HttpRequest, WeakHttpRequest};
use super::httprequest::HttpRequest;
use super::info::ConnectionInfo;
use super::response::WebResponse;
use super::rmap::ResourceMap;
@ -17,12 +17,12 @@ use super::rmap::ResourceMap;
/// An service http request
///
/// WebRequest allows mutable access to request's internal structures
pub struct WebRequest<Err> {
pub(super) req: HttpRequest,
_t: PhantomData<Err>,
pub struct WebRequest<'a, Err> {
pub(super) req: &'a mut HttpRequest,
_marker: PhantomData<fn(&'a ()) -> &'a Err>,
}
impl<Err: ErrorRenderer> WebRequest<Err> {
impl<'a, Err: ErrorRenderer> WebRequest<'a, Err> {
/// Create web response for error
#[inline]
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
pub(crate) fn new(req: HttpRequest) -> Self {
pub(crate) fn new(req: &'a mut HttpRequest) -> Self {
WebRequest {
req,
_t: PhantomData,
_marker: PhantomData,
}
}
pub(super) fn weak_request(&self) -> WeakHttpRequest {
self.req.downgrade()
}
// /// Deconstruct request into parts
// 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
pub fn into_parts(mut self) -> (HttpRequest, Payload) {
let pl = Rc::get_mut(&mut (self.req).0).unwrap().payload.take();
(self.req, pl)
}
// /// Construct request from parts.
// ///
// /// `WebRequest` can be re-constructed only if `req` hasnt been cloned.
// 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.
///
/// `WebRequest` can be re-constructed only if `req` hasnt been cloned.
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 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)
}
}
// /// 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
#[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 {
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]
/// Returns Request's headers.
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 {
writeln!(
f,

View file

@ -9,7 +9,7 @@ use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Tran
use crate::util::{Either, Extensions, Ready};
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::route::{IntoRoutes, Route, RouteService};
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.
/// Default behavior could be overriden with `default_resource()` method.
pub struct Resource<Err: ErrorRenderer, M = Identity, F = Filter<Err>> {
middleware: M,
pub struct Resource<Err: ErrorRenderer, M = Identity, F = Filter> {
filter: F,
middleware: M,
rdef: Vec<String>,
name: Option<String>,
routes: Vec<Route<Err>>,
@ -56,8 +56,8 @@ impl<'a, Err: ErrorRenderer> Resource<Err> {
routes: Vec::new(),
rdef: path.patterns(),
name: None,
filter: Filter,
middleware: Identity,
filter: Filter::new(),
guards: Vec::new(),
state: None,
default: Route::new().to(|| async { Response::MethodNotAllowed().finish() }),
@ -228,7 +228,7 @@ where
/// Register request filter.
///
/// 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 {
filter: Filters::new(self.filter, filter),
middleware: self.middleware,
@ -248,7 +248,7 @@ where
/// type (i.e modify response's body).
///
/// **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 {
middleware: Stack::new(self.middleware, mw),
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
M: Transform<
Next<
ResourceService<
<F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service,
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
Err,
>,
Err,
>,
> + 'static,
M::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
F: FiltersFactory<'a, Err>,
<F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Service: 'static,
<F::Service as ServiceFactory<&'a mut WebRequest<Err>>>::Future: 'static,
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 register(mut self, config: &mut WebServiceConfig<'a, Err>) {
@ -331,50 +330,41 @@ where
}
}
// impl<'a, Err, M, F> 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,
// {
// pub fn finish(self) -> impl ServiceFactory<&'a mut WebRequest<Err>, Response = WebResponse, Error = Err::Container, InitError = ()> {
// let router_factory = ResourceRouterFactory {
// routes: self.routes,
// state: self.state.map(Rc::new),
// default: self.default,
// };
impl<'a, Err, M, F>
IntoServiceFactory<
ResourceServiceFactory<Err, M, F::Service>,
&'a mut WebRequest<'a, Err>,
> for Resource<Err, M, F>
where
M: Transform<
Next<
ResourceService<
<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,
{
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, _, _> {
// middleware: Rc::new(MiddlewareStack::new(self.middleware)),
// filter: self.filter.create(),
// 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,
// }
// }
// }
ResourceServiceFactory {
middleware: Rc::new(MiddlewareStack::new(self.middleware)),
filter: self.filter.create(),
routing: router_factory,
}
}
}
/// Resource service
pub struct ResourceServiceFactory<Err: ErrorRenderer, M, F> {
@ -383,15 +373,15 @@ pub struct ResourceServiceFactory<Err: ErrorRenderer, M, F> {
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>
where
M: Transform<Next<ResourceService<F::Service, Err>, Err>> + 'static,
M: Transform<Next<ResourceService<F::Service, Err>>> + 'static,
M::Service:
Service<&'a mut WebRequest<Err>, Response = WebResponse, Error = Infallible>,
Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
F: ServiceFactory<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
InitError = (),
> + 'static,
@ -423,11 +413,11 @@ pub struct ResourceService<F, Err: ErrorRenderer> {
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
F: Service<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
>,
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 {
filter: self.filter.call(req),
routing: self.routing.clone(),
@ -457,19 +447,19 @@ where
}
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]
filter: F::Future,
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>
where
F: Service<
&'a mut WebRequest<Err>,
Response = &'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
>,
Err: ErrorRenderer,
@ -499,7 +489,7 @@ struct ResourceRouterFactory<Err: ErrorRenderer> {
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>
{
type Response = WebResponse;
@ -527,7 +517,7 @@ struct ResourceRouter<Err: ErrorRenderer> {
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 Error = Err::Container;
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(()))
}
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() {
if route.check(req) {
if let Some(ref state) = self.state {

View file

@ -8,8 +8,7 @@ use super::httprequest::HttpRequest;
/// An service http response
pub struct WebResponse {
// request: HttpRequest,
response: Response<Body>,
pub(super) response: Response<Body>,
}
impl WebResponse {
@ -21,10 +20,10 @@ impl WebResponse {
/// Create web response from the error
pub fn from_err<Err: ErrorRenderer, E: Into<Err::Container>>(
err: E,
request: HttpRequest,
request: &HttpRequest,
) -> Self {
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 {
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
#[inline]
pub fn into_response(self, response: Response) -> WebResponse {
WebResponse::new(response)
}
/// Get reference to original request
#[inline]
pub fn request(&self) -> &HttpRequest {
//&self.request
todo!()
}
/// Get reference to response
#[inline]
pub fn response(&self) -> &Response<Body> {
@ -90,21 +72,6 @@ impl WebResponse {
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
pub fn take_body(&mut self) -> ResponseBody<Body> {
self.response.take_body()
@ -115,21 +82,22 @@ impl WebResponse {
where
F: FnOnce(&mut ResponseHead, ResponseBody<Body>) -> ResponseBody<Body>,
{
let response = self.response.map_body(f);
WebResponse {
response,
// request: self.request,
response: self.response.map_body(f),
}
}
}
impl From<Response<Body>> for WebResponse {
#[inline]
fn from(response: Response<Body>) -> WebResponse {
WebResponse { response }
}
}
impl From<WebResponse> for Response<Body> {
fn from(mut res: WebResponse) -> Response<Body> {
let head = res.response.head_mut();
// if res.request.head().upgrade() {
// head.set_io(res.request.head());
// }
#[inline]
fn from(res: WebResponse) -> Response<Body> {
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 Error = Err::Container;
type InitError = ();
@ -65,7 +65,7 @@ pub struct RouteService<Err: ErrorRenderer> {
}
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) {
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 Error = Err::Container;
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]
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)
}
}
@ -181,7 +181,7 @@ impl<Err: ErrorRenderer> Route<Err> {
pub fn to<F, Args>(mut self, handler: F) -> Self
where
F: Handler<Args, Err>,
Args: FromRequest<Err> + 'static,
Args: FromRequest<'a, Err> + 'static,
Args::Error: Into<Err::Container>,
{
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 HttpService<Err: ErrorRenderer> =
BoxService<WebRequest<Err>, WebResponse, Err::Container>;
BoxService<&'a mut WebRequest<'a, Err>, WebResponse, Err::Container>;
type HttpNewService<Err: ErrorRenderer> =
BoxServiceFactory<(), WebRequest<Err>, WebResponse, Err::Container, ()>;
BoxServiceFactory<(), &'a mut WebRequest<'a, Err>, WebResponse, Err::Container, ()>;
type BoxResponse<Err: ErrorRenderer> =
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>> {
middleware: M,
filter: PipelineFactory<T, WebRequest<Err>>,
filter: PipelineFactory<T, &'a mut WebRequest<'a, Err>>,
rdef: Vec<String>,
state: Option<Extensions>,
services: Vec<Box<dyn AppServiceFactory<Err>>>,
@ -86,8 +86,8 @@ impl<Err: ErrorRenderer> Scope<Err> {
impl<Err, M, T> Scope<Err, M, T>
where
T: ServiceFactory<
WebRequest<Err>,
Response = WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
InitError = (),
>,
@ -286,8 +286,8 @@ where
/// If default resource is not registered, app's default resource is being used.
pub fn default_service<F, S>(mut self, f: F) -> Self
where
F: IntoServiceFactory<S, WebRequest<Err>>,
S: ServiceFactory<WebRequest<Err>, Response = WebResponse, Error = Err::Container>
F: IntoServiceFactory<S, &'a mut WebRequest<'a, Err>>,
S: ServiceFactory<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Err::Container>
+ 'static,
S::InitError: fmt::Debug,
{
@ -314,20 +314,20 @@ where
Err,
M,
impl ServiceFactory<
WebRequest<Err>,
Response = WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
InitError = (),
>,
>
where
U: ServiceFactory<
WebRequest<Err>,
Response = WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
InitError = (),
>,
F: IntoServiceFactory<U, WebRequest<Err>>,
F: IntoServiceFactory<U, &'a mut WebRequest<'a, Err>>,
{
Scope {
filter: self.filter.and_then(filter.into_factory()),
@ -370,13 +370,13 @@ where
impl<Err, M, T> WebServiceFactory<Err> for Scope<Err, M, T>
where
T: ServiceFactory<
WebRequest<Err>,
Response = WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
InitError = (),
> + '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,
{
fn register(mut self, config: &mut WebServiceConfig<Err>) {
@ -456,13 +456,13 @@ struct ScopeServiceFactory<M, F, Err: ErrorRenderer> {
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
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<
WebRequest<Err>,
Response = WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = &'a mut WebRequest<'a, Err>,
Error = Err::Container,
InitError = (),
> + 'static,
@ -492,9 +492,9 @@ pub struct ScopeService<F, Err: ErrorRenderer> {
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
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,
{
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 {
filter: self.filter.call(req),
routing: self.routing.clone(),
@ -522,17 +522,17 @@ where
}
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]
filter: F::Future,
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>
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,
{
type Output = Result<WebResponse, Err::Container>;
@ -561,7 +561,7 @@ struct ScopeRouterFactory<Err: ErrorRenderer> {
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 Error = Err::Container;
type InitError = ();
@ -610,7 +610,7 @@ struct ScopeRouter<Err: ErrorRenderer> {
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 Error = Err::Container;
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(()))
}
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| {
if let Some(guards) = 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::service::{IntoServiceFactory, ServiceFactory};
use crate::service::{IntoServiceFactory, Service, ServiceFactory};
use crate::util::Extensions;
use super::boxed::{self, BoxServiceFactory};
@ -11,33 +12,31 @@ use super::rmap::ResourceMap;
use super::types::state::StateFactory;
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>);
}
pub(super) trait AppServiceFactory<'a, Err: ErrorRenderer> {
pub(super) trait WebServiceWrapper<'a, Err: ErrorRenderer> {
fn register(&mut self, config: &mut WebServiceConfig<'a, Err>);
}
pub(super) struct ServiceFactoryWrapper<T> {
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>
pub(super) fn create_web_service<'a, T, Err>(svc: T) -> Box<dyn WebServiceWrapper<'a, Err>>
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,
T: WebServiceFactory<'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)
}
}
@ -131,7 +130,7 @@ impl<'a, Err: ErrorRenderer> WebServiceConfig<'a, Err> {
nested: Option<Rc<ResourceMap>>,
) where
S: ServiceFactory<
&'a mut WebRequest<Err>,
&'a mut WebRequest<'a, Err>,
Response = WebResponse,
Error = Err::Container,
InitError = (),
@ -209,9 +208,9 @@ impl WebServiceAdapter {
// /// Set a service factory implementation and generate web service.
// pub fn finish<'a, T, F, Err>(self, service: F) -> impl WebServiceFactory<'a, Err>
// where
// F: IntoServiceFactory<T, &'a mut WebRequest<Err>>,
// F: IntoServiceFactory<T, &'a mut WebRequest<'a, Err>>,
// T: ServiceFactory<
// &'a mut WebRequest<Err>,
// &'a mut WebRequest<'a, Err>,
// Response = WebResponse,
// Error = Err::Container,
// InitError = (),
@ -228,62 +227,62 @@ impl WebServiceAdapter {
// }
}
struct WebServiceImpl<T> {
srv: T,
rdef: Vec<String>,
name: Option<String>,
guards: Vec<Box<dyn Guard>>,
}
// struct WebServiceImpl<T> {
// srv: T,
// rdef: Vec<String>,
// name: Option<String>,
// guards: Vec<Box<dyn Guard>>,
// }
impl<'a, T, Err> WebServiceFactory<'a, Err> for WebServiceImpl<T>
where
T: ServiceFactory<
&'a mut WebRequest<Err>,
Response = WebResponse,
Error = Err::Container,
InitError = (),
> + 'static,
T::Future: 'static,
T::Service: 'static,
Err: ErrorRenderer,
{
fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
let guards = if self.guards.is_empty() {
None
} else {
Some(std::mem::take(&mut self.guards))
};
// impl<'a, T, Err> WebServiceFactory<'a, Err> for WebServiceImpl<T>
// where
// T: ServiceFactory<
// &'a mut WebRequest<'a, Err>,
// Response = WebResponse,
// Error = Err::Container,
// InitError = (),
// > + 'static,
// T::Future: 'static,
// T::Service: 'static,
// Err: ErrorRenderer,
// {
// fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
// let guards = if self.guards.is_empty() {
// None
// } else {
// Some(std::mem::take(&mut self.guards))
// };
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
ResourceDef::new(insert_slash(self.rdef))
} else {
ResourceDef::new(self.rdef)
};
if let Some(ref name) = self.name {
*rdef.name_mut() = name.clone();
}
config.register_service(rdef, guards, self.srv, None)
}
}
// let mut rdef = if config.is_root() || !self.rdef.is_empty() {
// ResourceDef::new(insert_slash(self.rdef))
// } else {
// ResourceDef::new(self.rdef)
// };
// if let Some(ref name) = self.name {
// *rdef.name_mut() = name.clone();
// }
// config.register_service(rdef, guards, self.srv, None)
// }
// }
/// WebServiceFactory implementation for a Vec<T>
#[allow(unused_parens)]
impl<'a, Err, T> WebServiceFactory<'a, Err> for Vec<T>
where
Err: ErrorRenderer,
T: WebServiceFactory<'a, Err> + 'static,
{
fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
for service in self.drain(..) {
service.register(config);
}
}
}
// /// WebServiceFactory implementation for a Vec<T>
// #[allow(unused_parens)]
// impl<'a, Err, T> WebServiceFactory<'a, Err> for Vec<T>
// where
// Err: ErrorRenderer,
// T: WebServiceFactory<'a, Err> + 'static,
// {
// fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
// for service in self.drain(..) {
// service.register(config);
// }
// }
// }
macro_rules! tuple_web_service({$(($n:tt, $T:ident)),+} => {
/// WebServiceFactory implementation for a tuple
#[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>) {
$(
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),+} => {
/// WebServiceFactory implementation for an array
#[allow(unused_parens)]
impl<'a, Err, T> WebServiceFactory<'a, Err> for [T; $num]
impl<'a, Err, T> WebService<'a, Err> for [T; $num]
where
Err: ErrorRenderer,
T: WebServiceFactory<'a, Err> + 'static,
T: WebService<'a, Err> + 'static,
{
fn register(self, config: &mut WebServiceConfig<'a, Err>) {
let [$($T,)+] = self;
@ -315,45 +314,45 @@ macro_rules! array_web_service({$num:tt, $($T:ident),+} => {
mod m {
use super::*;
array_web_service!(1,A);
array_web_service!(2,A,B);
array_web_service!(3,A,B,C);
array_web_service!(4,A,B,C,D);
array_web_service!(5,A,B,C,D,E);
array_web_service!(6,A,B,C,D,E,F);
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!(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!(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!(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!(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!(1,A);
array_web_service!(2,A,B);
array_web_service!(3,A,B,C);
array_web_service!(4,A,B,C,D);
array_web_service!(5,A,B,C,D,E);
array_web_service!(6,A,B,C,D,E,F);
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!(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!(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!(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!(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);
tuple_web_service!((0,A));
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),(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),(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),(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),(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),(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),(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),(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),(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),(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),(21,X));
tuple_web_service!((0,A));
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),(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),(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),(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),(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),(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),(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),(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),(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),(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),(21,X));
}
#[cfg(test)]

View file

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

View file

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