mirror of
https://github.com/fafhrd91/actix-net
synced 2025-02-20 06:30:32 +01:00
remove service dev module and add transformext trait
also improve docs on transform and boxed mods
This commit is contained in:
parent
0a705b1023
commit
91ea8c5dad
@ -1,12 +1,11 @@
|
|||||||
|
//! Trait object forms of services and service factories.
|
||||||
|
|
||||||
use alloc::{boxed::Box, rc::Rc};
|
use alloc::{boxed::Box, rc::Rc};
|
||||||
use core::{
|
use core::{future::Future, pin::Pin};
|
||||||
future::Future,
|
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{Service, ServiceFactory};
|
use crate::{Service, ServiceFactory};
|
||||||
|
|
||||||
|
/// A boxed future without a Send bound or lifetime parameters.
|
||||||
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
||||||
|
|
||||||
macro_rules! service_object {
|
macro_rules! service_object {
|
||||||
@ -23,17 +22,41 @@ macro_rules! service_object {
|
|||||||
Req: 'static,
|
Req: 'static,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
$type::new(ServiceWrapper(service))
|
$type::new(ServiceWrapper::new(service))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
service_object!(BoxService, Box, service);
|
service_object!(BoxService, Box, service);
|
||||||
|
|
||||||
service_object!(RcService, Rc, rc_service);
|
service_object!(RcService, Rc, rc_service);
|
||||||
|
|
||||||
/// Type alias for service factory trait object that would produce a trait object service
|
struct ServiceWrapper<S> {
|
||||||
/// (`BoxService`, `RcService`, etc.)
|
inner: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> ServiceWrapper<S> {
|
||||||
|
fn new(inner: S) -> Self {
|
||||||
|
Self { inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
|
||||||
|
where
|
||||||
|
S: Service<Req, Response = Res, Error = Err>,
|
||||||
|
S::Future: 'static,
|
||||||
|
{
|
||||||
|
type Response = Res;
|
||||||
|
type Error = Err;
|
||||||
|
type Future = BoxFuture<Result<Res, Err>>;
|
||||||
|
|
||||||
|
crate::forward_ready!(inner);
|
||||||
|
|
||||||
|
fn call(&self, req: Req) -> Self::Future {
|
||||||
|
Box::pin(self.inner.call(req))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for a service factory trait object that will produce a boxed trait object service.
|
||||||
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
|
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
|
||||||
|
|
||||||
/// Create service factory trait object.
|
/// Create service factory trait object.
|
||||||
@ -107,26 +130,6 @@ where
|
|||||||
|
|
||||||
fn new_service(&self, cfg: Cfg) -> Self::Future {
|
fn new_service(&self, cfg: Cfg) -> Self::Future {
|
||||||
let f = self.0.new_service(cfg);
|
let f = self.0.new_service(cfg);
|
||||||
Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper(s)) as _) })
|
Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as _) })
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ServiceWrapper<S>(S);
|
|
||||||
|
|
||||||
impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
|
|
||||||
where
|
|
||||||
S: Service<Req, Response = Res, Error = Err>,
|
|
||||||
S::Future: 'static,
|
|
||||||
{
|
|
||||||
type Response = Res;
|
|
||||||
type Error = Err;
|
|
||||||
type Future = BoxFuture<Result<Res, Err>>;
|
|
||||||
|
|
||||||
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
self.0.poll_ready(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&self, req: Req) -> Self::Future {
|
|
||||||
Box::pin(self.0.call(req))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::{dev, Service, ServiceFactory};
|
use crate::{
|
||||||
|
map::Map, map_err::MapErr, transform_err::TransformMapInitErr, Service, ServiceFactory,
|
||||||
|
Transform,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait ServiceExt<Req>: Service<Req> {
|
pub trait ServiceExt<Req>: Service<Req> {
|
||||||
/// Map this service's output to a different type, returning a new service
|
/// Map this service's output to a different type, returning a new service
|
||||||
@ -10,12 +13,12 @@ pub trait ServiceExt<Req>: Service<Req> {
|
|||||||
/// Note that this function consumes the receiving service and returns a
|
/// Note that this function consumes the receiving service and returns a
|
||||||
/// wrapped version of it, similar to the existing `map` methods in the
|
/// wrapped version of it, similar to the existing `map` methods in the
|
||||||
/// standard library.
|
/// standard library.
|
||||||
fn map<F, R>(self, f: F) -> dev::Map<Self, F, Req, R>
|
fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(Self::Response) -> R,
|
F: FnMut(Self::Response) -> R,
|
||||||
{
|
{
|
||||||
dev::Map::new(self, f)
|
Map::new(self, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map this service's error to a different error, returning a new service.
|
/// Map this service's error to a different error, returning a new service.
|
||||||
@ -26,12 +29,12 @@ pub trait ServiceExt<Req>: Service<Req> {
|
|||||||
///
|
///
|
||||||
/// Note that this function consumes the receiving service and returns a
|
/// Note that this function consumes the receiving service and returns a
|
||||||
/// wrapped version of it.
|
/// wrapped version of it.
|
||||||
fn map_err<F, E>(self, f: F) -> dev::MapErr<Self, Req, F, E>
|
fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: Fn(Self::Error) -> E,
|
F: Fn(Self::Error) -> E,
|
||||||
{
|
{
|
||||||
dev::MapErr::new(self, f)
|
MapErr::new(self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,4 +70,17 @@ pub trait ServiceFactoryExt<Req>: ServiceFactory<Req> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, Req> ServiceFactoryExt<Req> for S where S: ServiceFactory<Req> {}
|
impl<SF, Req> ServiceFactoryExt<Req> for SF where SF: ServiceFactory<Req> {}
|
||||||
|
|
||||||
|
pub trait TransformExt<S, Req>: Transform<S, Req> {
|
||||||
|
/// Return a new `Transform` whose init error is mapped to to a different type.
|
||||||
|
fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, Req, F, E>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: Fn(Self::InitError) -> E + Clone,
|
||||||
|
{
|
||||||
|
TransformMapInitErr::new(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, Req> TransformExt<T, Req> for T where T: Transform<T, Req> {}
|
||||||
|
@ -15,8 +15,7 @@ where
|
|||||||
|
|
||||||
/// Create `ServiceFactory` for function that can produce services
|
/// Create `ServiceFactory` for function that can produce services
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Examples
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::io;
|
/// use std::io;
|
||||||
/// use actix_service::{fn_factory, fn_service, Service, ServiceFactory};
|
/// use actix_service::{fn_factory, fn_service, Service, ServiceFactory};
|
||||||
@ -62,11 +61,10 @@ where
|
|||||||
|
|
||||||
/// Create `ServiceFactory` for function that accepts config argument and can produce services
|
/// Create `ServiceFactory` for function that accepts config argument and can produce services
|
||||||
///
|
///
|
||||||
/// Any function that has following form `Fn(Config) -> Future<Output = Service>` could
|
/// Any function that has following form `Fn(Config) -> Future<Output = Service>` could act as
|
||||||
/// act as a `ServiceFactory`.
|
/// a `ServiceFactory`.
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::io;
|
/// use std::io;
|
||||||
/// use actix_service::{fn_factory_with_config, fn_service, Service, ServiceFactory};
|
/// use actix_service::{fn_factory_with_config, fn_service, Service, ServiceFactory};
|
||||||
|
@ -34,11 +34,11 @@ mod transform_err;
|
|||||||
|
|
||||||
pub use self::apply::{apply_fn, apply_fn_factory};
|
pub use self::apply::{apply_fn, apply_fn_factory};
|
||||||
pub use self::apply_cfg::{apply_cfg, apply_cfg_factory};
|
pub use self::apply_cfg::{apply_cfg, apply_cfg_factory};
|
||||||
pub use self::ext::{ServiceExt, ServiceFactoryExt};
|
pub use self::ext::{ServiceExt, ServiceFactoryExt, TransformExt};
|
||||||
pub use self::fn_service::{fn_factory, fn_factory_with_config, fn_service};
|
pub use self::fn_service::{fn_factory, fn_factory_with_config, fn_service};
|
||||||
pub use self::map_config::{map_config, unit_config};
|
pub use self::map_config::{map_config, unit_config};
|
||||||
pub use self::pipeline::{pipeline, pipeline_factory, Pipeline, PipelineFactory};
|
pub use self::pipeline::{pipeline, pipeline_factory, Pipeline, PipelineFactory};
|
||||||
pub use self::transform::{apply, Transform};
|
pub use self::transform::{apply, ApplyTransform, Transform};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use self::ready::{err, ok, ready, Ready};
|
use self::ready::{err, ok, ready, Ready};
|
||||||
@ -220,6 +220,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This impl is deprecated since v2 because the `Service` trait now receives shared reference.
|
||||||
impl<S, Req> Service<Req> for RefCell<S>
|
impl<S, Req> Service<Req> for RefCell<S>
|
||||||
where
|
where
|
||||||
S: Service<Req>,
|
S: Service<Req>,
|
||||||
@ -313,16 +314,3 @@ where
|
|||||||
{
|
{
|
||||||
tp.into_service()
|
tp.into_service()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod dev {
|
|
||||||
pub use crate::apply::{Apply, ApplyFactory};
|
|
||||||
pub use crate::fn_service::{
|
|
||||||
FnService, FnServiceConfig, FnServiceFactory, FnServiceNoConfig,
|
|
||||||
};
|
|
||||||
pub use crate::map::{Map, MapServiceFactory};
|
|
||||||
pub use crate::map_config::{MapConfig, UnitConfig};
|
|
||||||
pub use crate::map_err::{MapErr, MapErrServiceFactory};
|
|
||||||
pub use crate::map_init_err::MapInitErr;
|
|
||||||
pub use crate::transform::ApplyTransform;
|
|
||||||
pub use crate::transform_err::TransformMapInitErr;
|
|
||||||
}
|
|
||||||
|
@ -9,10 +9,9 @@ use core::{
|
|||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use crate::transform_err::TransformMapInitErr;
|
|
||||||
use crate::{IntoServiceFactory, Service, ServiceFactory};
|
use crate::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
|
|
||||||
/// Apply transform to a service.
|
/// Apply a [`Transform`] to a [`Service`].
|
||||||
pub fn apply<T, S, I, Req>(t: T, factory: I) -> ApplyTransform<T, S, Req>
|
pub fn apply<T, S, I, Req>(t: T, factory: I) -> ApplyTransform<T, S, Req>
|
||||||
where
|
where
|
||||||
I: IntoServiceFactory<S, Req>,
|
I: IntoServiceFactory<S, Req>,
|
||||||
@ -25,9 +24,8 @@ where
|
|||||||
/// The `Transform` trait defines the interface of a service factory that wraps inner service
|
/// The `Transform` trait defines the interface of a service factory that wraps inner service
|
||||||
/// during construction.
|
/// during construction.
|
||||||
///
|
///
|
||||||
/// Transform(middleware) wraps inner service and runs during
|
/// Transform(middleware) wraps inner service and runs during inbound and/or outbound processing in
|
||||||
/// inbound and/or outbound processing in the request/response lifecycle.
|
/// the request/response lifecycle. It may modify request and/or response.
|
||||||
/// It may modify request and/or response.
|
|
||||||
///
|
///
|
||||||
/// For example, timeout transform:
|
/// For example, timeout transform:
|
||||||
///
|
///
|
||||||
@ -51,20 +49,19 @@ where
|
|||||||
/// fn call(&self, req: S::Request) -> Self::Future {
|
/// fn call(&self, req: S::Request) -> Self::Future {
|
||||||
/// TimeoutServiceResponse {
|
/// TimeoutServiceResponse {
|
||||||
/// fut: self.service.call(req),
|
/// fut: self.service.call(req),
|
||||||
/// sleep: Delay::new(clock::now() + self.timeout),
|
/// sleep: Sleep::new(clock::now() + self.timeout),
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Timeout service in above example is decoupled from underlying service implementation
|
/// Timeout service in above example is decoupled from underlying service implementation and could
|
||||||
/// and could be applied to any service.
|
/// be applied to any service.
|
||||||
///
|
///
|
||||||
/// The `Transform` trait defines the interface of a Service factory. `Transform`
|
/// The `Transform` trait defines the interface of a Service factory. `Transform` is often
|
||||||
/// is often implemented for middleware, defining how to construct a
|
/// implemented for middleware, defining how to construct a middleware Service. A Service that is
|
||||||
/// middleware Service. A Service that is constructed by the factory takes
|
/// constructed by the factory takes the Service that follows it during execution as a parameter,
|
||||||
/// the Service that follows it during execution as a parameter, assuming
|
/// assuming ownership of the next Service.
|
||||||
/// ownership of the next Service.
|
|
||||||
///
|
///
|
||||||
/// Factory for `Timeout` middleware from the above example could look like this:
|
/// Factory for `Timeout` middleware from the above example could look like this:
|
||||||
///
|
///
|
||||||
@ -85,15 +82,15 @@ where
|
|||||||
/// type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
/// type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||||
///
|
///
|
||||||
/// fn new_transform(&self, service: S) -> Self::Future {
|
/// fn new_transform(&self, service: S) -> Self::Future {
|
||||||
/// ok(TimeoutService {
|
/// ready(Ok(TimeoutService {
|
||||||
/// service,
|
/// service,
|
||||||
/// timeout: self.timeout,
|
/// timeout: self.timeout,
|
||||||
/// })
|
/// }))
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Transform<S, Req> {
|
pub trait Transform<S, Req> {
|
||||||
/// Responses given by the service.
|
/// Responses produced by the service.
|
||||||
type Response;
|
type Response;
|
||||||
|
|
||||||
/// Errors produced by the service.
|
/// Errors produced by the service.
|
||||||
@ -110,16 +107,6 @@ pub trait Transform<S, Req> {
|
|||||||
|
|
||||||
/// Creates and returns a new Transform component, asynchronously
|
/// Creates and returns a new Transform component, asynchronously
|
||||||
fn new_transform(&self, service: S) -> Self::Future;
|
fn new_transform(&self, service: S) -> Self::Future;
|
||||||
|
|
||||||
/// Map this transform's factory error to a different error,
|
|
||||||
/// returning a new transform service factory.
|
|
||||||
fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, Req, F, E>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
F: Fn(Self::InitError) -> E + Clone,
|
|
||||||
{
|
|
||||||
TransformMapInitErr::new(self, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S, Req> Transform<S, Req> for Rc<T>
|
impl<T, S, Req> Transform<S, Req> for Rc<T>
|
||||||
@ -152,7 +139,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Apply` transform to new service
|
/// Apply a [`Transform`] to a [`Service`].
|
||||||
pub struct ApplyTransform<T, S, Req>(Rc<(T, S)>, PhantomData<Req>);
|
pub struct ApplyTransform<T, S, Req>(Rc<(T, S)>, PhantomData<Req>);
|
||||||
|
|
||||||
impl<T, S, Req> ApplyTransform<T, S, Req>
|
impl<T, S, Req> ApplyTransform<T, S, Req>
|
||||||
|
@ -9,10 +9,8 @@ use pin_project_lite::pin_project;
|
|||||||
|
|
||||||
use super::Transform;
|
use super::Transform;
|
||||||
|
|
||||||
/// Transform for the `map_init_err` combinator, changing the type of a new
|
/// Transform for the [`TransformExt::map_init_err`] combinator, changing the type of a new
|
||||||
/// transform's init error.
|
/// [`Transform`]'s initialization error.
|
||||||
///
|
|
||||||
/// This is created by the `Transform::map_init_err` method.
|
|
||||||
pub struct TransformMapInitErr<T, S, Req, F, E> {
|
pub struct TransformMapInitErr<T, S, Req, F, E> {
|
||||||
transform: T,
|
transform: T,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use actix_service::{
|
use actix_service::{
|
||||||
apply, dev::ApplyTransform, IntoServiceFactory, Service, ServiceFactory, Transform,
|
apply, ApplyTransform, IntoServiceFactory, Service, ServiceFactory, Transform,
|
||||||
};
|
};
|
||||||
use futures_util::future::{ok, Either, Ready};
|
use futures_util::future::{ok, Either, Ready};
|
||||||
use tracing_futures::{Instrument, Instrumented};
|
use tracing_futures::{Instrument, Instrumented};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user