mirror of
https://github.com/ntex-rs/ntex.git
synced 2025-04-03 04:47:39 +03:00
fixes
This commit is contained in:
parent
4824b31b3c
commit
6d454a36eb
7 changed files with 358 additions and 256 deletions
|
@ -6,11 +6,11 @@ use crate::service::map_config;
|
||||||
use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Transform};
|
use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Transform};
|
||||||
use crate::util::Extensions;
|
use crate::util::Extensions;
|
||||||
|
|
||||||
use super::app_service::{AppFactory, AppFactoryInner, AppRouting, DefaultService};
|
use super::app_service::{AppFactory, AppFactoryInner, AppRouting};
|
||||||
use super::boxed::{self, BoxServiceFactory};
|
use super::boxed::{self, BoxServiceFactory};
|
||||||
use super::config::{AppConfig, ServiceConfig};
|
use super::config::{AppConfig, ServiceConfig};
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
use super::service::{create_web_service, WebService, WebServiceWrapper};
|
use super::service::{create_web_service, DefaultService, WebService, WebServiceWrapper};
|
||||||
use super::stack::{Filter, Filters, FiltersFactory, Next, Stack};
|
use super::stack::{Filter, Filters, FiltersFactory, Next, Stack};
|
||||||
use super::types::state::{State, StateFactory};
|
use super::types::state::{State, StateFactory};
|
||||||
use super::{DefaultError, ErrorRenderer, Resource, Route, WebRequest, WebResponse};
|
use super::{DefaultError, ErrorRenderer, Resource, Route, WebRequest, WebResponse};
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use std::convert::Infallible;
|
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::{cell::RefCell, future::Future, marker::PhantomData, pin::Pin, rc::Rc};
|
use std::{cell::RefCell, convert::Infallible, future::Future, pin::Pin, rc::Rc};
|
||||||
|
|
||||||
use crate::http::{Request, Response};
|
use crate::http::{Request, Response};
|
||||||
use crate::router::{Path, ResourceDef, Router};
|
use crate::router::{Path, ResourceDef, Router};
|
||||||
use crate::service::{Service, ServiceFactory, Transform};
|
use crate::service::{Service, ServiceFactory, Transform};
|
||||||
use crate::util::{ready, Either, Extensions, Ready};
|
use crate::util::{ready, Either, Extensions};
|
||||||
|
|
||||||
use super::boxed::{BoxService, BoxServiceFactory};
|
use super::boxed::{BoxService, BoxServiceFactory};
|
||||||
use super::httprequest::{HttpRequest, HttpRequestPool};
|
use super::httprequest::{HttpRequest, HttpRequestPool};
|
||||||
|
@ -135,43 +134,6 @@ where
|
||||||
pub(super) case_insensitive: bool,
|
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 = Infallible;
|
|
||||||
type InitError = ();
|
|
||||||
type Service = Self;
|
|
||||||
type Future = Ready<Self::Service, Self::InitError>;
|
|
||||||
|
|
||||||
fn new_service(&self, _: ()) -> Self::Future {
|
|
||||||
Ready::Ok(DefaultService(PhantomData))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for DefaultService<Err> {
|
|
||||||
type Response = WebResponse;
|
|
||||||
type Error = Infallible;
|
|
||||||
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>
|
impl<'a, T, F, Err> AppFactoryInner<'a, T, F, Err>
|
||||||
where
|
where
|
||||||
T: Transform<
|
T: Transform<
|
||||||
|
|
|
@ -17,10 +17,33 @@ use crate::util::{BytesMut, Either};
|
||||||
pub use super::error_default::DefaultError;
|
pub use super::error_default::DefaultError;
|
||||||
pub use crate::http::error::BlockingError;
|
pub use crate::http::error::BlockingError;
|
||||||
|
|
||||||
pub trait ErrorRenderer: Sized + 'static {}
|
pub trait ErrorRenderer: Sized + 'static {
|
||||||
|
#[inline]
|
||||||
|
/// Generate response for error
|
||||||
|
///
|
||||||
|
/// Internal server error is generated by default.
|
||||||
|
fn error_response<E: fmt::Display>(
|
||||||
|
err: E,
|
||||||
|
_: &HttpRequest,
|
||||||
|
st: StatusCode,
|
||||||
|
) -> HttpResponse {
|
||||||
|
let mut resp = HttpResponse::new(st);
|
||||||
|
let mut buf = BytesMut::new();
|
||||||
|
let _ = write!(Writer(&mut buf), "{}", err);
|
||||||
|
resp.headers_mut().insert(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
header::HeaderValue::from_static("text/plain; charset=utf-8"),
|
||||||
|
);
|
||||||
|
resp.set_body(Body::from(buf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error that can be rendered to a `Response`
|
/// Error that can be rendered to a `Response`
|
||||||
pub trait Error<Err = DefaultError>: fmt::Display + fmt::Debug + Sized {
|
pub trait Error<Err = DefaultError>: fmt::Display + fmt::Debug + Sized
|
||||||
|
where
|
||||||
|
Err: ErrorRenderer,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
/// Response's status code
|
/// Response's status code
|
||||||
///
|
///
|
||||||
/// Internal server error is generated by default.
|
/// Internal server error is generated by default.
|
||||||
|
@ -28,18 +51,13 @@ pub trait Error<Err = DefaultError>: fmt::Display + fmt::Debug + Sized {
|
||||||
StatusCode::INTERNAL_SERVER_ERROR
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Generate response for error
|
/// Generate response for error
|
||||||
///
|
///
|
||||||
/// Internal server error is generated by default.
|
/// Internal server error is generated by default.
|
||||||
fn error_response(self, _: &HttpRequest) -> HttpResponse {
|
fn error_response(self, req: &HttpRequest) -> HttpResponse {
|
||||||
let mut resp = HttpResponse::new(self.status_code());
|
let st = self.status_code();
|
||||||
let mut buf = BytesMut::new();
|
<Err as ErrorRenderer>::error_response(self, req, st)
|
||||||
let _ = write!(Writer(&mut buf), "{}", self);
|
|
||||||
resp.headers_mut().insert(
|
|
||||||
header::CONTENT_TYPE,
|
|
||||||
header::HeaderValue::from_static("text/plain; charset=utf-8"),
|
|
||||||
);
|
|
||||||
resp.set_body(Body::from(buf))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod app_service;
|
mod app_service;
|
||||||
|
mod boxed;
|
||||||
mod config;
|
mod config;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod error_default;
|
mod error_default;
|
||||||
|
@ -80,7 +81,6 @@ mod response;
|
||||||
mod rmap;
|
mod rmap;
|
||||||
mod route;
|
mod route;
|
||||||
// mod scope;
|
// mod scope;
|
||||||
mod boxed;
|
|
||||||
mod server;
|
mod server;
|
||||||
mod service;
|
mod service;
|
||||||
mod stack;
|
mod stack;
|
||||||
|
|
|
@ -1,29 +1,26 @@
|
||||||
use std::task::{Context, Poll};
|
use std::{
|
||||||
use std::{cell::RefCell, fmt, future::Future, convert::Infallible, pin::Pin, rc::Rc};
|
cell::RefCell, fmt, future::Future, pin::Pin, rc::Rc, task::Context, task::Poll,
|
||||||
|
};
|
||||||
|
use std::{convert::Infallible, marker::PhantomData};
|
||||||
|
|
||||||
use crate::http::Response;
|
|
||||||
use crate::router::{IntoPattern, ResourceDef, Router};
|
use crate::router::{IntoPattern, ResourceDef, Router};
|
||||||
use crate::service::boxed::{self, BoxService, BoxServiceFactory};
|
|
||||||
use crate::service::{pipeline_factory, PipelineFactory};
|
|
||||||
use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Transform};
|
use crate::service::{Identity, IntoServiceFactory, Service, ServiceFactory, Transform};
|
||||||
use crate::util::{Either, Extensions, Ready};
|
use crate::util::{ready, Extensions};
|
||||||
|
|
||||||
use super::config::ServiceConfig;
|
use super::boxed::{self, BoxService, BoxServiceFactory};
|
||||||
use super::dev::{WebServiceConfig, WebServiceFactory};
|
use super::config::{AppConfig, ServiceConfig};
|
||||||
|
use super::error::Error;
|
||||||
use super::guard::Guard;
|
use super::guard::Guard;
|
||||||
use super::rmap::ResourceMap;
|
use super::rmap::ResourceMap;
|
||||||
use super::service::{AppServiceFactory, ServiceFactoryWrapper};
|
use super::service::{WebService, WebServiceConfig, DefaultService};
|
||||||
use super::stack::{Filter, Next, Stack, MiddlewareStack, Middleware};
|
use super::stack::{
|
||||||
|
Filter, Filters, FiltersFactory, Middleware, MiddlewareStack, Next, Services,
|
||||||
|
ServicesFactory, Stack,
|
||||||
|
};
|
||||||
use super::types::State;
|
use super::types::State;
|
||||||
use super::{ErrorRenderer, Resource, Route, WebRequest, WebResponse};
|
use super::{ErrorRenderer, Resource, Route, WebRequest, WebResponse};
|
||||||
|
|
||||||
type Guards = Vec<Box<dyn Guard>>;
|
type Guards = Vec<Box<dyn Guard>>;
|
||||||
type HttpService<Err: ErrorRenderer> =
|
|
||||||
BoxService<&'a mut WebRequest<'a, Err>, WebResponse, Err::Container>;
|
|
||||||
type HttpNewService<Err: ErrorRenderer> =
|
|
||||||
BoxServiceFactory<(), &'a mut WebRequest<'a, Err>, WebResponse, Err::Container, ()>;
|
|
||||||
type BoxResponse<Err: ErrorRenderer> =
|
|
||||||
Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>>>>;
|
|
||||||
|
|
||||||
/// Resources scope.
|
/// Resources scope.
|
||||||
///
|
///
|
||||||
|
@ -54,43 +51,39 @@ type BoxResponse<Err: ErrorRenderer> =
|
||||||
/// * /{project_id}/path2 - `GET` requests
|
/// * /{project_id}/path2 - `GET` requests
|
||||||
/// * /{project_id}/path3 - `HEAD` requests
|
/// * /{project_id}/path3 - `HEAD` requests
|
||||||
///
|
///
|
||||||
pub struct Scope<Err: ErrorRenderer, M = Identity, T = Filter<Err>> {
|
pub struct Scope<Err: ErrorRenderer, S = Identity, M = Identity, F = Filter> {
|
||||||
|
service: S,
|
||||||
|
filter: F,
|
||||||
middleware: M,
|
middleware: M,
|
||||||
filter: PipelineFactory<T, &'a mut WebRequest<'a, Err>>,
|
|
||||||
rdef: Vec<String>,
|
rdef: Vec<String>,
|
||||||
state: Option<Extensions>,
|
state: Option<Extensions>,
|
||||||
services: Vec<Box<dyn AppServiceFactory<Err>>>,
|
// default: BoxServiceFactory<'a, Err>,
|
||||||
guards: Vec<Box<dyn Guard>>,
|
guards: Vec<Box<dyn Guard>>,
|
||||||
default: Rc<RefCell<Option<Rc<HttpNewService<Err>>>>>,
|
|
||||||
external: Vec<ResourceDef>,
|
external: Vec<ResourceDef>,
|
||||||
case_insensitive: bool,
|
case_insensitive: bool,
|
||||||
|
_marker: PhantomData<Err>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Err: ErrorRenderer> Scope<Err> {
|
impl<Err: ErrorRenderer> Scope<Err> {
|
||||||
/// Create a new scope
|
/// Create a new scope
|
||||||
pub fn new<T: IntoPattern>(path: T) -> Scope<Err> {
|
pub fn new<T: IntoPattern>(path: T) -> Scope<Err> {
|
||||||
Scope {
|
Scope {
|
||||||
|
service: Identity,
|
||||||
|
filter: Filter,
|
||||||
middleware: Identity,
|
middleware: Identity,
|
||||||
filter: pipeline_factory(Filter::new()),
|
|
||||||
rdef: path.patterns(),
|
rdef: path.patterns(),
|
||||||
state: None,
|
state: None,
|
||||||
guards: Vec::new(),
|
guards: Vec::new(),
|
||||||
services: Vec::new(),
|
// default: boxed::factory(DefaultService::default()),
|
||||||
default: Rc::new(RefCell::new(None)),
|
|
||||||
external: Vec::new(),
|
external: Vec::new(),
|
||||||
case_insensitive: false,
|
case_insensitive: false,
|
||||||
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Err, M, T> Scope<Err, M, T>
|
impl<Err, S, M, F> Scope<Err, S, M, F>
|
||||||
where
|
where
|
||||||
T: ServiceFactory<
|
|
||||||
&'a mut WebRequest<'a, Err>,
|
|
||||||
Response = &'a mut WebRequest<'a, Err>,
|
|
||||||
Error = Err::Container,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
Err: ErrorRenderer,
|
Err: ErrorRenderer,
|
||||||
{
|
{
|
||||||
/// Add match guard to a scope.
|
/// Add match guard to a scope.
|
||||||
|
@ -195,24 +188,24 @@ where
|
||||||
/// .route("/index.html", web::get().to(|| async { HttpResponse::Ok() }));
|
/// .route("/index.html", web::get().to(|| async { HttpResponse::Ok() }));
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn configure<F>(mut self, f: F) -> Self
|
pub fn configure<'a, U>(mut self, f: U) -> Self
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ServiceConfig<Err>),
|
U: FnOnce(&mut ServiceConfig<'a, Err>),
|
||||||
{
|
{
|
||||||
let mut cfg = ServiceConfig::new();
|
//let mut cfg = ServiceConfig::new();
|
||||||
f(&mut cfg);
|
//f(&mut cfg);
|
||||||
self.services.extend(cfg.services);
|
//self.services.extend(cfg.services);
|
||||||
self.external.extend(cfg.external);
|
//self.external.extend(cfg.external);
|
||||||
|
|
||||||
if !cfg.state.is_empty() {
|
// if !cfg.state.is_empty() {
|
||||||
let mut state = self.state.unwrap_or_else(Extensions::new);
|
// let mut state = self.state.unwrap_or_else(Extensions::new);
|
||||||
|
|
||||||
for value in cfg.state.iter() {
|
// for value in cfg.state.iter() {
|
||||||
value.create(&mut state);
|
// value.create(&mut state);
|
||||||
}
|
// }
|
||||||
|
|
||||||
self.state = Some(state);
|
// self.state = Some(state);
|
||||||
}
|
// }
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,13 +236,19 @@ where
|
||||||
/// );
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn service<F>(mut self, factory: F) -> Self
|
pub fn service<U>(self, factory: U) -> Scope<Err, Services<S, Next<U>>, M, F> {
|
||||||
where
|
Scope {
|
||||||
F: WebServiceFactory<Err> + 'static,
|
service: Services::new(self.service, Next::new(factory)),
|
||||||
{
|
filter: self.filter,
|
||||||
self.services
|
middleware: self.middleware,
|
||||||
.push(Box::new(ServiceFactoryWrapper::new(factory)));
|
rdef: self.rdef,
|
||||||
self
|
state: self.state,
|
||||||
|
guards: self.guards,
|
||||||
|
// default: self.default,
|
||||||
|
external: self.external,
|
||||||
|
case_insensitive: self.case_insensitive,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure route for a specific path.
|
/// Configure route for a specific path.
|
||||||
|
@ -273,7 +272,11 @@ where
|
||||||
/// );
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn route(self, path: &str, mut route: Route<Err>) -> Self {
|
pub fn route(
|
||||||
|
self,
|
||||||
|
path: &str,
|
||||||
|
mut route: Route<Err>,
|
||||||
|
) -> Scope<Err, Services<S, Next<Resource<Err>>>, M, F> {
|
||||||
self.service(
|
self.service(
|
||||||
Resource::new(path)
|
Resource::new(path)
|
||||||
.add_guards(route.take_guards())
|
.add_guards(route.take_guards())
|
||||||
|
@ -284,18 +287,20 @@ where
|
||||||
/// Default service to be used if no matching route could be found.
|
/// Default service to be used if no matching route could be found.
|
||||||
///
|
///
|
||||||
/// If default resource is not registered, app's default resource is being used.
|
/// If default resource is not registered, app's default resource is being used.
|
||||||
pub fn default_service<F, S>(mut self, f: F) -> Self
|
pub fn default<'a, T, U>(mut self, f: T) -> Self
|
||||||
where
|
where
|
||||||
F: IntoServiceFactory<S, &'a mut WebRequest<'a, Err>>,
|
T: IntoServiceFactory<U, &'a mut WebRequest<'a, Err>>,
|
||||||
S: ServiceFactory<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Err::Container>
|
U: ServiceFactory<&'a mut WebRequest<'a, Err>, Response = WebResponse> + 'static,
|
||||||
+ 'static,
|
U::Service: 'static,
|
||||||
S::InitError: fmt::Debug,
|
U::Future: 'static,
|
||||||
|
U::Error: Error<Err>,
|
||||||
|
U::InitError: fmt::Debug + 'static,
|
||||||
{
|
{
|
||||||
// create and configure default resource
|
// create and configure default resource
|
||||||
self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::factory(
|
//self.default =
|
||||||
f.into_factory()
|
// boxed::factory(f.into_factory().map_init_err(|e| {
|
||||||
.map_init_err(|e| log::error!("Cannot construct default service: {:?}", e)),
|
// log::error!("Cannot construct default service: {:?}", e)
|
||||||
)))));
|
// }));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -307,38 +312,18 @@ where
|
||||||
/// necessary, across all requests managed by the *Scope*.
|
/// necessary, across all requests managed by the *Scope*.
|
||||||
///
|
///
|
||||||
/// This is similar to `App's` filters, but filter get invoked on scope level.
|
/// This is similar to `App's` filters, but filter get invoked on scope level.
|
||||||
pub fn filter<U, F>(
|
pub fn filter<U>(self, filter: U) -> Scope<Err, S, M, Filters<F, Next<U>>> {
|
||||||
self,
|
|
||||||
filter: F,
|
|
||||||
) -> Scope<
|
|
||||||
Err,
|
|
||||||
M,
|
|
||||||
impl ServiceFactory<
|
|
||||||
&'a mut WebRequest<'a, Err>,
|
|
||||||
Response = &'a mut WebRequest<'a, Err>,
|
|
||||||
Error = Err::Container,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
>
|
|
||||||
where
|
|
||||||
U: ServiceFactory<
|
|
||||||
&'a mut WebRequest<'a, Err>,
|
|
||||||
Response = &'a mut WebRequest<'a, Err>,
|
|
||||||
Error = Err::Container,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
F: IntoServiceFactory<U, &'a mut WebRequest<'a, Err>>,
|
|
||||||
{
|
|
||||||
Scope {
|
Scope {
|
||||||
filter: self.filter.and_then(filter.into_factory()),
|
filter: Filters::new(self.filter, Next::new(filter)),
|
||||||
|
service: self.service,
|
||||||
middleware: self.middleware,
|
middleware: self.middleware,
|
||||||
rdef: self.rdef,
|
rdef: self.rdef,
|
||||||
state: self.state,
|
state: self.state,
|
||||||
guards: self.guards,
|
guards: self.guards,
|
||||||
services: self.services,
|
// default: self.default,
|
||||||
default: self.default,
|
|
||||||
external: self.external,
|
external: self.external,
|
||||||
case_insensitive: self.case_insensitive,
|
case_insensitive: self.case_insensitive,
|
||||||
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,46 +337,53 @@ where
|
||||||
/// WebResponse.
|
/// WebResponse.
|
||||||
///
|
///
|
||||||
/// Use middleware when you need to read or modify *every* request in some way.
|
/// Use middleware when you need to read or modify *every* request in some way.
|
||||||
pub fn wrap<U>(self, mw: U) -> Scope<Err, Stack<M, U, Err>, T> {
|
pub fn wrap<U>(self, mw: U) -> Scope<Err, S, Stack<M, U>, F> {
|
||||||
Scope {
|
Scope {
|
||||||
middleware: Stack::new(self.middleware, mw),
|
middleware: Stack::new(self.middleware, mw),
|
||||||
filter: self.filter,
|
filter: self.filter,
|
||||||
|
service: self.service,
|
||||||
rdef: self.rdef,
|
rdef: self.rdef,
|
||||||
state: self.state,
|
state: self.state,
|
||||||
guards: self.guards,
|
guards: self.guards,
|
||||||
services: self.services,
|
// default: self.default,
|
||||||
default: self.default,
|
|
||||||
external: self.external,
|
external: self.external,
|
||||||
case_insensitive: self.case_insensitive,
|
case_insensitive: self.case_insensitive,
|
||||||
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Err, M, T> WebServiceFactory<Err> for Scope<Err, M, T>
|
impl<'a, Err, S, M, F> WebService<'a, Err> for Scope<Err, S, M, F>
|
||||||
where
|
where
|
||||||
T: ServiceFactory<
|
S: ServicesFactory<'a, Err> + 'static,
|
||||||
&'a mut WebRequest<'a, Err>,
|
M: Transform<
|
||||||
Response = &'a mut WebRequest<'a, Err>,
|
ScopeService<
|
||||||
Error = Err::Container,
|
'a,
|
||||||
InitError = (),
|
<F::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service,
|
||||||
> + 'static,
|
Err,
|
||||||
M: Transform<Next<ScopeService<T::Service, Err>, Err>> + 'static,
|
>,
|
||||||
|
> + 'static,
|
||||||
M::Service: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
|
M::Service: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
|
||||||
|
<M::Service as Service<&'a mut WebRequest<'a, Err>>>::Future: 'a,
|
||||||
|
|
||||||
|
F: FiltersFactory<'a, Err> + 'static,
|
||||||
Err: ErrorRenderer,
|
Err: ErrorRenderer,
|
||||||
{
|
{
|
||||||
fn register(mut self, config: &mut WebServiceConfig<Err>) {
|
fn register(mut self, config: &mut WebServiceConfig<'a, Err>) {
|
||||||
// update default resource if needed
|
// update default resource if needed
|
||||||
if self.default.borrow().is_none() {
|
//if self.default.borrow().is_none() {
|
||||||
*self.default.borrow_mut() = Some(config.default_service());
|
// *self.default.borrow_mut() = Some(config.default_service());
|
||||||
}
|
//}
|
||||||
|
|
||||||
// register nested services
|
// // register nested services
|
||||||
let mut cfg = config.clone_config();
|
// let mut cfg: WebServiceConfig<'a, Err> = WebServiceConfig::<'a, _>::new(
|
||||||
self.services
|
// config.config.clone(),
|
||||||
.into_iter()
|
// Rc::new(boxed::factory(DefaultService::default())),
|
||||||
.for_each(|mut srv| srv.register(&mut cfg));
|
// config.service_state.clone()
|
||||||
|
// );
|
||||||
|
// self.service.register(&mut cfg);
|
||||||
|
|
||||||
let slesh = self.rdef.iter().any(|s| s.ends_with('/'));
|
let slash = self.rdef.iter().any(|s| s.ends_with('/'));
|
||||||
let mut rmap = ResourceMap::new(ResourceDef::root_prefix(self.rdef.clone()));
|
let mut rmap = ResourceMap::new(ResourceDef::root_prefix(self.rdef.clone()));
|
||||||
|
|
||||||
// external resources
|
// external resources
|
||||||
|
@ -400,33 +392,33 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom app data storage
|
// custom app data storage
|
||||||
if let Some(ref mut ext) = self.state {
|
//if let Some(ref mut ext) = self.state {
|
||||||
config.set_service_state(ext);
|
// config.set_service_state(ext);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// complete scope pipeline creation
|
// complete scope pipeline creation
|
||||||
let router_factory = ScopeRouterFactory {
|
// let router_factory: ScopeRouterFactory<'a, Err> = ScopeRouterFactory {
|
||||||
state: self.state.take().map(Rc::new),
|
// state: self.state.take().map(Rc::new),
|
||||||
default: self.default.clone(),
|
// // default: self.default.clone(),
|
||||||
case_insensitive: self.case_insensitive,
|
// case_insensitive: self.case_insensitive,
|
||||||
services: Rc::new(
|
// services: Rc::new(
|
||||||
cfg.into_services()
|
// cfg.into_services()
|
||||||
.1
|
// .1
|
||||||
.into_iter()
|
// .into_iter()
|
||||||
.map(|(rdef, srv, guards, nested)| {
|
// .map(|(rdef, srv, guards, nested)| {
|
||||||
// case for scope prefix ends with '/' and
|
// // case for scope prefix ends with '/' and
|
||||||
// resource is empty pattern
|
// // resource is empty pattern
|
||||||
let mut rdef = if slesh && rdef.pattern() == "" {
|
// let mut rdef = if slesh && rdef.pattern() == "" {
|
||||||
ResourceDef::new("/")
|
// ResourceDef::new("/")
|
||||||
} else {
|
// } else {
|
||||||
rdef
|
// rdef
|
||||||
};
|
// };
|
||||||
rmap.add(&mut rdef, nested);
|
// rmap.add(&mut rdef, nested);
|
||||||
(rdef, srv, RefCell::new(guards))
|
// (rdef, srv, RefCell::new(guards))
|
||||||
})
|
// })
|
||||||
.collect(),
|
// .collect(),
|
||||||
),
|
// ),
|
||||||
};
|
// };
|
||||||
|
|
||||||
// get guards
|
// get guards
|
||||||
let guards = if self.guards.is_empty() {
|
let guards = if self.guards.is_empty() {
|
||||||
|
@ -440,9 +432,14 @@ where
|
||||||
ResourceDef::root_prefix(self.rdef),
|
ResourceDef::root_prefix(self.rdef),
|
||||||
guards,
|
guards,
|
||||||
ScopeServiceFactory {
|
ScopeServiceFactory {
|
||||||
|
slash,
|
||||||
|
config: config.config.clone(),
|
||||||
middleware: Rc::new(MiddlewareStack::new(self.middleware)),
|
middleware: Rc::new(MiddlewareStack::new(self.middleware)),
|
||||||
filter: self.filter,
|
filter: self.filter.create(),
|
||||||
routing: router_factory,
|
state: self.state.take().map(Rc::new),
|
||||||
|
// default: self.default.clone(),
|
||||||
|
case_insensitive: self.case_insensitive,
|
||||||
|
service: self.service,
|
||||||
},
|
},
|
||||||
Some(Rc::new(rmap)),
|
Some(Rc::new(rmap)),
|
||||||
)
|
)
|
||||||
|
@ -450,33 +447,79 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scope service
|
/// Scope service
|
||||||
struct ScopeServiceFactory<M, F, Err: ErrorRenderer> {
|
struct ScopeServiceFactory<Err: ErrorRenderer, S, M, F> {
|
||||||
|
config: AppConfig,
|
||||||
middleware: Rc<MiddlewareStack<M, Err>>,
|
middleware: Rc<MiddlewareStack<M, Err>>,
|
||||||
filter: F,
|
filter: F,
|
||||||
routing: ScopeRouterFactory<Err>,
|
service: S,
|
||||||
|
state: Option<Rc<Extensions>>,
|
||||||
|
slash: bool,
|
||||||
|
case_insensitive: bool,
|
||||||
|
// default: Rc<RefCell<Option<Rc<BoxServiceFactory<'a, Err>>>>>,
|
||||||
|
// routing: ScopeRouterFactory<'a, Err>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, F, Err> ServiceFactory<&'a mut WebRequest<'a, Err>> for ScopeServiceFactory<M, F, Err>
|
impl<'a, Err, S, M, F> ServiceFactory<&'a mut WebRequest<'a, Err>> for ScopeServiceFactory<Err, S, M, F>
|
||||||
where
|
where
|
||||||
M: Transform<Next<ScopeService<F::Service, Err>, Err>> + 'static,
|
S: ServicesFactory<'a, Err> + 'static,
|
||||||
|
M: Transform<ScopeService<'a, F::Service, Err>> + 'static,
|
||||||
M::Service: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
|
M::Service: Service<&'a mut WebRequest<'a, Err>, Response = WebResponse, Error = Infallible>,
|
||||||
F: ServiceFactory<
|
F: ServiceFactory<
|
||||||
&'a mut WebRequest<'a, Err>,
|
&'a mut WebRequest<'a, Err>,
|
||||||
Response = &'a mut WebRequest<'a, Err>,
|
Response = &'a mut WebRequest<'a, Err>,
|
||||||
Error = Err::Container,
|
Error = Infallible,
|
||||||
InitError = (),
|
InitError = (),
|
||||||
> + 'static,
|
> + 'static,
|
||||||
|
F::Service: 'static,
|
||||||
|
F::Future: 'static,
|
||||||
Err: ErrorRenderer,
|
Err: ErrorRenderer,
|
||||||
{
|
{
|
||||||
type Response = WebResponse;
|
type Response = WebResponse;
|
||||||
type Error = Err::Container;
|
type Error = Infallible;
|
||||||
type Service = Middleware<M::Service, Err>;
|
type Service = Middleware<M::Service, Err>;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
|
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
|
||||||
|
|
||||||
fn new_service(&self, _: ()) -> Self::Future {
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
// register nested services
|
||||||
|
let mut cfg: WebServiceConfig<'a, Err> = WebServiceConfig::<'a, _>::new(
|
||||||
|
self.config.clone(),
|
||||||
|
Rc::new(boxed::factory(DefaultService::default())),
|
||||||
|
Rc::new(Vec::new()),
|
||||||
|
);
|
||||||
|
|
||||||
|
// custom app data storage
|
||||||
|
if let Some(ref mut ext) = self.state {
|
||||||
|
cfg.set_service_state(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// complete scope pipeline creation
|
||||||
|
self.service.register(&mut cfg);
|
||||||
|
|
||||||
|
let router_factory: ScopeRouterFactory<'a, Err> = ScopeRouterFactory {
|
||||||
|
state: self.state.take(),
|
||||||
|
// default: self.default.clone(),
|
||||||
|
case_insensitive: self.case_insensitive,
|
||||||
|
services: Rc::new(
|
||||||
|
cfg.into_services()
|
||||||
|
.1
|
||||||
|
.into_iter()
|
||||||
|
.map(|(rdef, srv, guards, nested)| {
|
||||||
|
// case for scope prefix ends with '/' and
|
||||||
|
// resource is empty pattern
|
||||||
|
let mut rdef = if self.slash && rdef.pattern() == "" {
|
||||||
|
ResourceDef::new("/")
|
||||||
|
} else {
|
||||||
|
rdef
|
||||||
|
};
|
||||||
|
(rdef, srv, RefCell::new(guards))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
let filter_fut = self.filter.new_service(());
|
let filter_fut = self.filter.new_service(());
|
||||||
let routing_fut = self.routing.new_service(());
|
let routing_fut = router_factory.new_service(());
|
||||||
let middleware = self.middleware.clone();
|
let middleware = self.middleware.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
Ok(middleware.new_transform(ScopeService {
|
Ok(middleware.new_transform(ScopeService {
|
||||||
|
@ -487,24 +530,28 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ScopeService<F, Err: ErrorRenderer> {
|
pub struct ScopeService<'a, F, Err: ErrorRenderer> {
|
||||||
filter: F,
|
filter: F,
|
||||||
routing: Rc<ScopeRouter<Err>>,
|
routing: Rc<ScopeRouter<'a, Err>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, Err> Service<&'a mut WebRequest<'a, Err>> for ScopeService<F, Err>
|
impl<'a, F, Err> Service<&'a mut WebRequest<'a, Err>> for ScopeService<'a, F, Err>
|
||||||
where
|
where
|
||||||
F: Service<&'a mut WebRequest<'a, Err>, Response = &'a mut WebRequest<'a, Err>, Error = Err::Container>,
|
F: Service<
|
||||||
|
&'a mut WebRequest<'a, Err>,
|
||||||
|
Response = &'a mut WebRequest<'a, Err>,
|
||||||
|
Error = Infallible,
|
||||||
|
>,
|
||||||
Err: ErrorRenderer,
|
Err: ErrorRenderer,
|
||||||
{
|
{
|
||||||
type Response = WebResponse;
|
type Response = WebResponse;
|
||||||
type Error = Err::Container;
|
type Error = Infallible;
|
||||||
type Future = ScopeServiceResponse<F, Err>;
|
type Future = ScopeServiceResponse<'a, F, Err>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
let ready1 = self.filter.poll_ready(cx)?.is_ready();
|
let ready1 = self.filter.poll_ready(cx).is_ready();
|
||||||
let ready2 = self.routing.poll_ready(cx)?.is_ready();
|
let ready2 = self.routing.poll_ready(cx).is_ready();
|
||||||
if ready1 && ready2 {
|
if ready1 && ready2 {
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -522,20 +569,24 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_project_lite::pin_project! {
|
pin_project_lite::pin_project! {
|
||||||
pub struct ScopeServiceResponse<F: Service<&'a mut WebRequest<'a, Err>>, Err: ErrorRenderer> {
|
pub struct ScopeServiceResponse<'a, F: Service<&'a mut WebRequest<'a, Err>>, Err: ErrorRenderer> {
|
||||||
#[pin]
|
#[pin]
|
||||||
filter: F::Future,
|
filter: F::Future,
|
||||||
routing: Rc<ScopeRouter<Err>>,
|
routing: Rc<ScopeRouter<'a, Err>>,
|
||||||
endpoint: Option<<ScopeRouter<Err> as Service<&'a mut WebRequest<'a, Err>>>::Future>,
|
endpoint: Option<<ScopeRouter<'a, Err> as Service<&'a mut WebRequest<'a, Err>>>::Future>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, Err> Future for ScopeServiceResponse<F, Err>
|
impl<'a, F, Err> Future for ScopeServiceResponse<'a, F, Err>
|
||||||
where
|
where
|
||||||
F: Service<&'a mut WebRequest<'a, Err>, Response = &'a mut WebRequest<'a, Err>, Error = Err::Container>,
|
F: Service<
|
||||||
|
&'a mut WebRequest<'a, Err>,
|
||||||
|
Response = &'a mut WebRequest<'a, Err>,
|
||||||
|
Error = Infallible,
|
||||||
|
>,
|
||||||
Err: ErrorRenderer,
|
Err: ErrorRenderer,
|
||||||
{
|
{
|
||||||
type Output = Result<WebResponse, Err::Container>;
|
type Output = Result<WebResponse, Infallible>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let this = self.as_mut().project();
|
let this = self.as_mut().project();
|
||||||
|
@ -543,40 +594,44 @@ where
|
||||||
if let Some(fut) = this.endpoint.as_mut() {
|
if let Some(fut) = this.endpoint.as_mut() {
|
||||||
Pin::new(fut).poll(cx)
|
Pin::new(fut).poll(cx)
|
||||||
} else {
|
} else {
|
||||||
let res = if let Poll::Ready(res) = this.filter.poll(cx) {
|
let req = ready!(this.filter.poll(cx)).unwrap();
|
||||||
res?
|
*this.endpoint = Some(this.routing.call(req));
|
||||||
} else {
|
|
||||||
return Poll::Pending;
|
|
||||||
};
|
|
||||||
*this.endpoint = Some(this.routing.call(res));
|
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScopeRouterFactory<Err: ErrorRenderer> {
|
struct ScopeRouterFactory<'a, Err: ErrorRenderer> {
|
||||||
state: Option<Rc<Extensions>>,
|
state: Option<Rc<Extensions>>,
|
||||||
services: Rc<Vec<(ResourceDef, HttpNewService<Err>, RefCell<Option<Guards>>)>>,
|
services: Rc<
|
||||||
default: Rc<RefCell<Option<Rc<HttpNewService<Err>>>>>,
|
Vec<(
|
||||||
|
ResourceDef,
|
||||||
|
BoxServiceFactory<'a, Err>,
|
||||||
|
RefCell<Option<Guards>>,
|
||||||
|
)>,
|
||||||
|
>,
|
||||||
|
// default: Rc<RefCell<Option<Rc<BoxServiceFactory<'a, Err>>>>>,
|
||||||
case_insensitive: bool,
|
case_insensitive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>> for ScopeRouterFactory<Err> {
|
impl<'a, Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>>
|
||||||
|
for ScopeRouterFactory<'a, Err>
|
||||||
|
{
|
||||||
type Response = WebResponse;
|
type Response = WebResponse;
|
||||||
type Error = Err::Container;
|
type Error = Infallible;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
type Service = ScopeRouter<Err>;
|
type Service = ScopeRouter<'a, Err>;
|
||||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
|
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
|
||||||
|
|
||||||
fn new_service(&self, _: ()) -> Self::Future {
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
let services = self.services.clone();
|
let services = self.services.clone();
|
||||||
let case_insensitive = self.case_insensitive;
|
let case_insensitive = self.case_insensitive;
|
||||||
let state = self.state.clone();
|
let state = self.state.clone();
|
||||||
let default_fut = self
|
// let default_fut = self
|
||||||
.default
|
// .default
|
||||||
.borrow()
|
// .borrow()
|
||||||
.as_ref()
|
// .as_ref()
|
||||||
.map(|srv| srv.new_service(()));
|
// .map(|srv| srv.new_service(()));
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// create http services
|
// create http services
|
||||||
|
@ -589,31 +644,31 @@ impl<Err: ErrorRenderer> ServiceFactory<&'a mut WebRequest<'a, Err>> for ScopeRo
|
||||||
router.rdef(path.clone(), service).2 = guards.borrow_mut().take();
|
router.rdef(path.clone(), service).2 = guards.borrow_mut().take();
|
||||||
}
|
}
|
||||||
|
|
||||||
let default = if let Some(fut) = default_fut {
|
// let default = if let Some(fut) = default_fut {
|
||||||
Some(fut.await?)
|
// Some(fut.await?)
|
||||||
} else {
|
// } else {
|
||||||
None
|
// None
|
||||||
};
|
// };
|
||||||
|
|
||||||
Ok(ScopeRouter {
|
Ok(ScopeRouter {
|
||||||
state,
|
state,
|
||||||
default,
|
// default,
|
||||||
router: router.finish(),
|
router: router.finish(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScopeRouter<Err: ErrorRenderer> {
|
struct ScopeRouter<'a, Err: ErrorRenderer> {
|
||||||
state: Option<Rc<Extensions>>,
|
state: Option<Rc<Extensions>>,
|
||||||
router: Router<HttpService<Err>, Vec<Box<dyn Guard>>>,
|
router: Router<BoxService<'a, Err>, Vec<Box<dyn Guard>>>,
|
||||||
default: Option<HttpService<Err>>,
|
// default: Option<BoxService<'a, Err>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for ScopeRouter<Err> {
|
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for ScopeRouter<'a, Err> {
|
||||||
type Response = WebResponse;
|
type Response = WebResponse;
|
||||||
type Error = Err::Container;
|
type Error = Infallible;
|
||||||
type Future = Either<BoxResponse<Err>, Ready<Self::Response, Self::Error>>;
|
type Future = Pin<Box<dyn Future<Output = Result<WebResponse, Infallible>> + 'a>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
@ -621,7 +676,7 @@ impl<Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for ScopeRouter<Er
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, mut req: &'a mut WebRequest<'a, Err>) -> Self::Future {
|
fn call(&self, mut req: &'a mut WebRequest<'a, Err>) -> Self::Future {
|
||||||
let res = self.router.recognize_checked(&mut req, |req, guards| {
|
let res = self.router.recognize_checked(req, |req, guards| {
|
||||||
if let Some(guards) = guards {
|
if let Some(guards) = guards {
|
||||||
for f in guards {
|
for f in guards {
|
||||||
if !f.check(req.head()) {
|
if !f.check(req.head()) {
|
||||||
|
@ -636,15 +691,10 @@ impl<Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for ScopeRouter<Er
|
||||||
if let Some(ref state) = self.state {
|
if let Some(ref state) = self.state {
|
||||||
req.set_state_container(state.clone());
|
req.set_state_container(state.clone());
|
||||||
}
|
}
|
||||||
Either::Left(srv.call(req))
|
srv.call(req)
|
||||||
} else if let Some(ref default) = self.default {
|
|
||||||
Either::Left(default.call(req))
|
|
||||||
} else {
|
} else {
|
||||||
let req = req.into_parts().0;
|
//self.default.call(req)
|
||||||
Either::Right(Ready::Ok(WebResponse::new(
|
todo!()
|
||||||
Response::NotFound().finish(),
|
|
||||||
// req,
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
use std::rc::Rc;
|
use std::{convert::Infallible, marker::PhantomData, rc::Rc, task::Context, task::Poll};
|
||||||
|
|
||||||
use crate::router::{IntoPattern, ResourceDef};
|
use crate::router::{IntoPattern, ResourceDef};
|
||||||
use crate::service::{IntoServiceFactory, ServiceFactory};
|
use crate::service::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
use crate::util::Extensions;
|
use crate::util::{Extensions, Ready};
|
||||||
|
|
||||||
use super::boxed::{self, BoxServiceFactory};
|
use super::boxed::{self, BoxServiceFactory};
|
||||||
use super::types::state::StateFactory;
|
use super::types::state::StateFactory;
|
||||||
use super::{config::AppConfig, dev::insert_slash, rmap::ResourceMap};
|
use super::{config::AppConfig, dev::insert_slash, rmap::ResourceMap};
|
||||||
use super::{error::Error, guard::Guard, ErrorRenderer, WebRequest, WebResponse};
|
use super::{
|
||||||
|
error::Error, guard::Guard, ErrorRenderer, HttpResponse, WebRequest, WebResponse,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait WebService<'a, Err: ErrorRenderer>: 'static {
|
pub trait WebService<'a, Err: ErrorRenderer>: 'static {
|
||||||
fn register(self, config: &mut WebServiceConfig<'a, Err>);
|
fn register(self, config: &mut WebServiceConfig<'a, Err>);
|
||||||
|
@ -43,16 +45,16 @@ type Guards = Vec<Box<dyn Guard>>;
|
||||||
|
|
||||||
/// Application service configuration
|
/// Application service configuration
|
||||||
pub struct WebServiceConfig<'a, Err: ErrorRenderer> {
|
pub struct WebServiceConfig<'a, Err: ErrorRenderer> {
|
||||||
config: AppConfig,
|
pub(super) config: AppConfig,
|
||||||
root: bool,
|
root: bool,
|
||||||
default: Rc<BoxServiceFactory<'a, Err>>,
|
pub(super) default: Rc<BoxServiceFactory<'a, Err>>,
|
||||||
services: Vec<(
|
services: Vec<(
|
||||||
ResourceDef,
|
ResourceDef,
|
||||||
BoxServiceFactory<'a, Err>,
|
BoxServiceFactory<'a, Err>,
|
||||||
Option<Guards>,
|
Option<Guards>,
|
||||||
Option<Rc<ResourceMap>>,
|
Option<Rc<ResourceMap>>,
|
||||||
)>,
|
)>,
|
||||||
service_state: Rc<Vec<Box<dyn StateFactory>>>,
|
pub(super) service_state: Rc<Vec<Box<dyn StateFactory>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Err: ErrorRenderer> WebServiceConfig<'a, Err> {
|
impl<'a, Err: ErrorRenderer> WebServiceConfig<'a, Err> {
|
||||||
|
@ -90,7 +92,7 @@ impl<'a, Err: ErrorRenderer> WebServiceConfig<'a, Err> {
|
||||||
(self.config, self.services)
|
(self.config, self.services)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clone_config(&self) -> Self {
|
pub(super) fn clone_config(&'a self) -> WebServiceConfig<'a, Err> {
|
||||||
WebServiceConfig {
|
WebServiceConfig {
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
default: self.default.clone(),
|
default: self.default.clone(),
|
||||||
|
@ -267,6 +269,43 @@ where
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#[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 = Infallible;
|
||||||
|
type InitError = ();
|
||||||
|
type Service = Self;
|
||||||
|
type Future = Ready<Self::Service, Self::InitError>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
Ready::Ok(DefaultService(PhantomData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Err: ErrorRenderer> Service<&'a mut WebRequest<'a, Err>> for DefaultService<Err> {
|
||||||
|
type Response = WebResponse;
|
||||||
|
type Error = Infallible;
|
||||||
|
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(HttpResponse::NotFound().finish().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! tuple_web_service({$(($n:tt, $T:ident)),+} => {
|
macro_rules! tuple_web_service({$(($n:tt, $T:ident)),+} => {
|
||||||
/// WebServiceFactory implementation for a tuple
|
/// WebServiceFactory implementation for a tuple
|
||||||
#[allow(unused_parens)]
|
#[allow(unused_parens)]
|
||||||
|
|
|
@ -3,10 +3,10 @@ use std::{
|
||||||
task::Poll,
|
task::Poll,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::service::{dev::AndThenFactory, Service, ServiceFactory, Transform};
|
use crate::service::{dev::AndThenFactory, Identity, Service, ServiceFactory, Transform};
|
||||||
use crate::util::{ready, Ready};
|
use crate::util::{ready, Ready};
|
||||||
|
|
||||||
use super::{Error, ErrorRenderer, WebRequest, WebResponse};
|
use super::{Error, ErrorRenderer, WebRequest, WebResponse, WebService, WebServiceConfig};
|
||||||
|
|
||||||
pub struct Stack<Inner, Outer> {
|
pub struct Stack<Inner, Outer> {
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
|
@ -233,6 +233,7 @@ where
|
||||||
> + 'static,
|
> + 'static,
|
||||||
First::Service: 'static,
|
First::Service: 'static,
|
||||||
First::Future: 'static,
|
First::Future: 'static,
|
||||||
|
<First::Service as Service<&'a mut WebRequest<'a, Err>>>::Future: 'a,
|
||||||
Second: FiltersFactory<'a, Err>,
|
Second: FiltersFactory<'a, Err>,
|
||||||
Second::Service: ServiceFactory<
|
Second::Service: ServiceFactory<
|
||||||
&'a mut WebRequest<'a, Err>,
|
&'a mut WebRequest<'a, Err>,
|
||||||
|
@ -242,6 +243,7 @@ where
|
||||||
>,
|
>,
|
||||||
<Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
|
<Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service: 'static,
|
||||||
<Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
|
<Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Future: 'static,
|
||||||
|
<<Second::Service as ServiceFactory<&'a mut WebRequest<'a, Err>>>::Service as Service<&'a mut WebRequest<'a, Err>>>::Future: 'a,
|
||||||
{
|
{
|
||||||
type Service = AndThenFactory<First, Second::Service>;
|
type Service = AndThenFactory<First, Second::Service>;
|
||||||
|
|
||||||
|
@ -260,3 +262,34 @@ pub trait FiltersFactory<'a, Err: ErrorRenderer> {
|
||||||
|
|
||||||
fn create(self) -> Self::Service;
|
fn create(self) -> Self::Service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, Err: ErrorRenderer> ServicesFactory<'a, Err> for Identity {
|
||||||
|
fn register(self, _: &mut WebServiceConfig<'a, Err>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Services<First, Second> {
|
||||||
|
first: First,
|
||||||
|
second: Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<First, Second> Services<First, Second> {
|
||||||
|
pub(super) fn new(first: First, second: Second) -> Self {
|
||||||
|
Services { first, second }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, First, Second, Err> ServicesFactory<'a, Err> for Services<First, Second>
|
||||||
|
where
|
||||||
|
Err: ErrorRenderer,
|
||||||
|
First: WebService<'a, Err>,
|
||||||
|
Second: ServicesFactory<'a, Err>,
|
||||||
|
{
|
||||||
|
fn register(self, cfg: &mut WebServiceConfig<'a, Err>) {
|
||||||
|
self.second.register(cfg);
|
||||||
|
self.first.register(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ServicesFactory<'a, Err: ErrorRenderer> {
|
||||||
|
fn register(self, cfg: &mut WebServiceConfig<'a, Err>);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue