diff --git a/actix-codec/src/lib.rs b/actix-codec/src/lib.rs index 6348b58f..fc53b688 100644 --- a/actix-codec/src/lib.rs +++ b/actix-codec/src/lib.rs @@ -7,7 +7,6 @@ //! [`AsyncRead`]: # //! [`AsyncWrite`]: # #![deny(rust_2018_idioms, warnings)] -#![allow(clippy::type_complexity)] mod bcodec; mod framed; diff --git a/actix-service/Cargo.toml b/actix-service/Cargo.toml index 4c83afb6..cf690a20 100644 --- a/actix-service/Cargo.toml +++ b/actix-service/Cargo.toml @@ -2,14 +2,13 @@ name = "actix-service" version = "1.0.0-alpha.4" authors = ["Nikolay Kim "] -description = "Actix Service" +description = "Actix service" keywords = ["network", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net.git" documentation = "https://docs.rs/actix-service/" categories = ["network-programming", "asynchronous"] license = "MIT/Apache-2.0" -exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] edition = "2018" workspace = ".." diff --git a/actix-service/src/fn_service.rs b/actix-service/src/fn_service.rs index 698cd052..225e56b9 100644 --- a/actix-service/src/fn_service.rs +++ b/actix-service/src/fn_service.rs @@ -18,6 +18,41 @@ where } /// Create `ServiceFactory` for function that can produce services +/// +/// # Example +/// +/// ```rust +/// use std::io; +/// use actix_service::{fn_factory, fn_service, Service, ServiceFactory}; +/// use futures_util::future::ok; +/// +/// /// Service that divides two usize values. +/// async fn div((x, y): (usize, usize)) -> Result { +/// if y == 0 { +/// Err(io::Error::new(io::ErrorKind::Other, "divide by zdro")) +/// } else { +/// Ok(x / y) +/// } +/// } +/// +/// #[actix_rt::main] +/// async fn main() -> io::Result<()> { +/// // Create service factory that produces `div` services +/// let factory = fn_factory(|| { +/// ok::<_, io::Error>(fn_service(div)) +/// }); +/// +/// // construct new service +/// let mut srv = factory.new_service(()).await?; +/// +/// // now we can use `div` service +/// let result = srv.call((10, 20)).await?; +/// +/// println!("10 / 20 = {}", result); +/// +/// Ok(()) +/// } +/// ``` pub fn fn_factory(f: F) -> FnServiceNoConfig where Srv: Service, @@ -27,7 +62,36 @@ where FnServiceNoConfig::new(f) } -/// Create `ServiceFactory` for function that accepts config 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` could +/// act as a `ServiceFactory`. +/// +/// # Example +/// +/// ```rust +/// use std::io; +/// use actix_service::{fn_factory_with_config, fn_service, Service, ServiceFactory}; +/// use futures_util::future::ok; +/// +/// #[actix_rt::main] +/// async fn main() -> io::Result<()> { +/// // Create service factory. factory uses config argument for +/// // services it generates. +/// let factory = fn_factory_with_config(|y: usize| { +/// ok::<_, io::Error>(fn_service(move |x: usize| ok::<_, io::Error>(x * y))) +/// }); +/// +/// // construct new service with config argument +/// let mut srv = factory.new_service(10).await?; +/// +/// let result = srv.call(10).await?; +/// assert_eq!(result, 100); +/// +/// println!("10 * 10 = {}", result); +/// Ok(()) +/// } +/// ``` pub fn fn_factory_with_config( f: F, ) -> FnServiceConfig diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs index bcd2dd06..2b0a876a 100644 --- a/actix-service/src/lib.rs +++ b/actix-service/src/lib.rs @@ -31,6 +31,42 @@ pub use self::pipeline::{pipeline, pipeline_factory, Pipeline, PipelineFactory}; pub use self::transform::{apply, Transform}; /// An asynchronous function from `Request` to a `Response`. +/// +/// `Service` represents a service that represanting interation, taking requests and giving back +/// replies. You can think about service as a function with one argument and result as a return +/// type. In general form it looks like `async fn(Req) -> Result`. `Service` +/// trait just generalizing form of this function. Each parameter described as an assotiated type. +/// +/// Services provides a symmetric and uniform API, same abstractions represents +/// clients and servers. Services describe only `transforamtion` operation +/// which encorouge to simplify api surface and phrases `value transformation`. +/// That leads to simplier design of each service. That also allows better testability +/// and better composition. +/// +/// Services could be represented in several different forms. In general, +/// Service is a type that implements `Service` trait. +/// +/// ```rust,ignore +/// struct MyService; +/// +/// impl Service for MyService { +/// type Request = u8; +/// type Response = u64; +/// type Error = MyError; +/// type Future = Pin>>; +/// +/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { ... } +/// +/// fn call(&mut self) -> Self::Future { ... } +/// } +/// ``` +/// +/// Service can have mutable state that influence computation. +/// This service could be rewritten as a simple function: +/// +/// ```rust,ignore +/// async fn my_service(req: u8) -> Result; +/// ``` pub trait Service { /// Requests handled by the service. type Request; @@ -53,6 +89,12 @@ pub trait Service { /// This is a **best effort** implementation. False positives are permitted. /// It is permitted for the service to return `Ready` from a `poll_ready` /// call and the next invocation of `call` results in an error. + /// + /// There are several notes to consider: + /// + /// 1. `.poll_ready()` might be called on different task from actual service call. + /// + /// 2. In case of chained services, `.poll_ready()` get called for all services at once. fn poll_ready(&mut self, ctx: &mut task::Context<'_>) -> Poll>; /// Process the request and return the response asynchronously. @@ -287,7 +329,7 @@ pub trait IntoServiceFactory where T: ServiceFactory, { - /// Convert `Self` an `ServiceFactory` + /// Convert `Self` to a `ServiceFactory` fn into_factory(self) -> T; } diff --git a/actix-service/src/map_config.rs b/actix-service/src/map_config.rs index a2997f54..40b27c7d 100644 --- a/actix-service/src/map_config.rs +++ b/actix-service/src/map_config.rs @@ -2,7 +2,10 @@ use std::marker::PhantomData; use super::ServiceFactory; -/// Adapt external config to a config for provided new service +/// Adapt external config argument to a config for provided service factory +/// +/// Note that this function consumes the receiving service factory and returns +/// a wrapped version of it. pub fn map_config(factory: T, f: F) -> MapConfig where T: ServiceFactory, diff --git a/actix-service/src/pipeline.rs b/actix-service/src/pipeline.rs index c04a284e..b101f837 100644 --- a/actix-service/src/pipeline.rs +++ b/actix-service/src/pipeline.rs @@ -9,6 +9,7 @@ use crate::map_init_err::MapInitErr; use crate::then::{ThenService, ThenServiceFactory}; use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory}; +/// Contruct new pipeline with one service in pipeline chain. pub fn pipeline(service: F) -> Pipeline where F: IntoService, @@ -19,6 +20,7 @@ where } } +/// Contruct new pipeline factory with one service factory. pub fn pipeline_factory(factory: F) -> PipelineFactory where T: ServiceFactory, diff --git a/actix-service/src/transform.rs b/actix-service/src/transform.rs index 5f6730f5..dbc32df8 100644 --- a/actix-service/src/transform.rs +++ b/actix-service/src/transform.rs @@ -19,11 +19,78 @@ where ApplyTransform::new(t, service.into_factory()) } +/// The `Transform` trait defines the interface of a service factory that wraps inner service +/// during construction. +/// +/// Transform(middleware) wraps inner service and runs during +/// inbound and/or outbound processing in the request/response lifecycle. +/// It may modify request and/or response. +/// +/// For example, timeout transform: +/// +/// ```rust,ignore +/// pub struct Timeout { +/// service: S, +/// timeout: Duration, +/// } +/// +/// impl Service for Timeout +/// where +/// S: Service, +/// { +/// type Request = S::Request; +/// type Response = S::Response; +/// type Error = TimeoutError; +/// type Future = TimeoutServiceResponse; +/// +/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { +/// ready!(self.service.poll_ready(cx)).map_err(TimeoutError::Service) +/// } +/// +/// fn call(&mut self, req: S::Request) -> Self::Future { +/// TimeoutServiceResponse { +/// fut: self.service.call(req), +/// sleep: Delay::new(clock::now() + self.timeout), +/// } +/// } +/// } +/// ``` +/// +/// Timeout service in above example is decoupled from underlying service implementation +/// and could be applied to any service. +/// /// The `Transform` trait defines the interface of a Service factory. `Transform` /// is often implemented for middleware, defining how to construct a /// middleware Service. A Service that is constructed by the factory takes /// the Service that follows it during execution as a parameter, assuming /// ownership of the next Service. +/// +/// Factory for `Timeout` middleware from the above example could look like this: +/// +/// ```rust,,ignore +/// pub struct TimeoutTransform { +/// timeout: Duration, +/// } +/// +/// impl Transform for TimeoutTransform +/// where +/// S: Service, +/// { +/// type Request = S::Request; +/// type Response = S::Response; +/// type Error = TimeoutError; +/// type InitError = S::Error; +/// type Transform = Timeout; +/// type Future = Ready>; +/// +/// fn new_transform(&self, service: S) -> Self::Future { +/// ok(TimeoutService { +/// service, +/// timeout: self.timeout, +/// }) +/// } +/// } +/// ``` pub trait Transform { /// Requests handled by the service. type Request; @@ -41,13 +108,13 @@ pub trait Transform { Error = Self::Error, >; - /// Errors produced while building a service. + /// Errors produced while building a transform service. type InitError; /// The future response value. type Future: Future>; - /// Creates and returns a new Service component, asynchronously + /// Creates and returns a new Transform component, asynchronously fn new_transform(&self, service: S) -> Self::Future; /// Map this transforms's factory error to a different error, diff --git a/actix-tls/src/openssl.rs b/actix-tls/src/openssl.rs index e9dd8a78..66fde444 100644 --- a/actix-tls/src/openssl.rs +++ b/actix-tls/src/openssl.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; -pub use open_ssl::ssl::{SslAcceptor, SslAcceptorBuilder, AlpnError}; +pub use open_ssl::ssl::{AlpnError, SslAcceptor, SslAcceptorBuilder}; pub use tokio_openssl::{HandshakeError, SslStream}; use actix_codec::{AsyncRead, AsyncWrite};