1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-25 01:20:37 +00:00

move service to separate crate

This commit is contained in:
Nikolay Kim 2018-12-09 09:56:23 -08:00
parent e8aa73a44b
commit 5f37d85f9b
14 changed files with 183 additions and 74 deletions

View file

@ -16,7 +16,7 @@ matrix:
env:
global:
# - RUSTFLAGS="-C link-dead-code"
- RUSTFLAGS="-C link-dead-code"
- OPENSSL_VERSION=openssl-1.0.2
before_install:
@ -33,6 +33,7 @@ script:
if [[ "$TRAVIS_RUST_VERSION" != "nightly" ]]; then
cargo clean
cargo test --features="ssl,tls,rust-tls" -- --nocapture
cd actix-service && cargo test
fi
- |
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
@ -40,6 +41,7 @@ script:
cargo tarpaulin --features="ssl,tls,rust-tls" --out Xml
bash <(curl -s https://codecov.io/bash)
echo "Uploaded code coverage"
cd actix-service && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash)
fi
# Upload docs

View file

@ -13,6 +13,12 @@ license = "MIT/Apache-2.0"
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
edition = "2018"
[workspace]
members = [
"./",
"actix-service",
]
[package.metadata.docs.rs]
features = ["ssl", "tls", "rust-tls"]
@ -41,6 +47,8 @@ cell = []
[dependencies]
actix = "0.7.6"
# actix-service = "0.1"
actix-service = { path="./actix-service" }
log = "0.4"
num_cpus = "1.0"

26
actix-service/Cargo.toml Normal file
View file

@ -0,0 +1,26 @@
[package]
name = "actix-service"
version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
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 = "../"
[badges]
travis-ci = { repository = "actix/actix-service", branch = "master" }
# appveyor = { repository = "fafhrd91/actix-web-hdy9d" }
codecov = { repository = "actix/actix-service", branch = "master", service = "github" }
[lib]
name = "actix_service"
path = "src/lib.rs"
[dependencies]
futures = "0.1.24"

View file

@ -46,7 +46,7 @@ where
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
try_ready!(self.a.poll_ready());
self.b.borrow_mut().poll_ready()
self.b.get_mut().poll_ready()
}
fn call(&mut self, req: Request) -> Self::Future {
@ -82,7 +82,6 @@ impl<A, B, Request> Future for AndThenFuture<A, B, Request>
where
A: Service<Request>,
B: Service<A::Response, Error = A::Error>,
B::Error: Into<A::Error>,
{
type Item = B::Response;
type Error = A::Error;
@ -94,7 +93,7 @@ where
match self.fut_a.poll() {
Ok(Async::Ready(resp)) => {
self.fut_b = Some(self.b.borrow_mut().call(resp));
self.fut_b = Some(self.b.get_mut().call(resp));
self.poll()
}
Ok(Async::NotReady) => Ok(Async::NotReady),
@ -219,7 +218,7 @@ mod tests {
use std::rc::Rc;
use super::*;
use crate::service::{NewServiceExt, Service, ServiceExt};
use crate::{NewService, Service};
struct Srv1(Rc<Cell<usize>>);
impl Service<&'static str> for Srv1 {

View file

@ -50,8 +50,8 @@ where
F: Fn(In, &mut T) -> Out,
Out: IntoFuture,
{
type Response = <Out::Future as Future>::Item;
type Error = <Out::Future as Future>::Error;
type Response = Out::Item;
type Error = Out::Error;
type Future = Out::Future;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
@ -110,8 +110,8 @@ where
F: Fn(In, &mut T::Service) -> Out + Clone,
Out: IntoFuture,
{
type Response = <Out::Future as Future>::Item;
type Error = <Out::Future as Future>::Error;
type Response = Out::Item;
type Error = Out::Error;
type Service = Apply<T::Service, F, In, Out, Request>;
type InitError = T::InitError;
@ -171,9 +171,7 @@ mod tests {
use futures::future::{ok, FutureResult};
use futures::{Async, Future, Poll};
use crate::service::{
IntoNewService, IntoService, NewService, NewServiceExt, Service, ServiceExt,
};
use crate::{IntoNewService, IntoService, NewService, Service};
#[derive(Clone)]
struct Srv;

32
actix-service/src/cell.rs Normal file
View file

@ -0,0 +1,32 @@
//! Custom cell impl
use std::{cell::UnsafeCell, fmt, rc::Rc};
pub(crate) struct Cell<T> {
inner: Rc<UnsafeCell<T>>,
}
impl<T> Clone for Cell<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T: fmt::Debug> fmt::Debug for Cell<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<T> Cell<T> {
pub(crate) fn new(inner: T) -> Self {
Self {
inner: Rc::new(UnsafeCell::new(inner)),
}
}
pub(crate) fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.inner.as_ref().get() }
}
}

View file

@ -159,7 +159,7 @@ mod tests {
use futures::future::{err, FutureResult};
use super::*;
use crate::service::{IntoNewService, NewServiceExt, Service, ServiceExt};
use crate::{IntoNewService, NewService, Service};
struct Srv;
impl Service<()> for Srv {

View file

@ -1,10 +1,7 @@
use futures::{Future, IntoFuture};
/// re-export for convinience
pub use tower_service::Service;
use futures::{Future, IntoFuture, Poll};
mod and_then;
mod apply;
mod cell;
mod fn_service;
mod from_err;
mod map;
@ -21,9 +18,39 @@ pub use self::map_err::{MapErr, MapErrNewService};
pub use self::map_init_err::MapInitErr;
pub use self::then::{Then, ThenNewService};
/// An extension trait for `Service`s that provides a variety of convenient
/// adapters
pub trait ServiceExt<Request>: Service<Request> {
/// An asynchronous function from `Request` to a `Response`.
pub trait Service<Request> {
/// Responses given by the service.
type Response;
/// Errors produced by the service.
type Error;
/// The future response value.
type Future: Future<Item = Self::Response, Error = Self::Error>;
/// Returns `Ready` when the service is able to process requests.
///
/// If the service is at capacity, then `NotReady` is returned and the task
/// is notified when the service becomes ready again. This function is
/// expected to be called while on a task.
///
/// 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.
fn poll_ready(&mut self) -> Poll<(), Self::Error>;
/// Process the request and return the response asynchronously.
///
/// This function is expected to be callable off task. As such,
/// implementations should take care to not call `poll_ready`. If the
/// service is at capacity and the request is unable to be handled, the
/// returned `Future` should resolve to an error.
///
/// Calling `call` without calling `poll_ready` is permitted. The
/// implementation must be resilient to this fact.
fn call(&mut self, req: Request) -> Self::Future;
/// Apply function to specified service and use it as a next service in
/// chain.
fn apply<T, I, F, Out, Req>(
@ -33,7 +60,7 @@ pub trait ServiceExt<Request>: Service<Request> {
) -> AndThen<Self, Apply<T, F, Self::Response, Out, Req>>
where
Self: Sized,
T: Service<Req, Error = Out::Error>,
T: Service<Req, Error = Self::Error>,
I: IntoService<T, Req>,
F: Fn(Self::Response, &mut T) -> Out,
Out: IntoFuture<Error = Self::Error>,
@ -59,11 +86,11 @@ pub trait ServiceExt<Request>: Service<Request> {
AndThen::new(self, service.into_service())
}
// /// Map this service's error to any error implementing `From` for
// /// this service`s `Error`.
// ///
// /// Note that this function consumes the receiving service and returns a
// /// wrapped version of it.
/// Map this service's error to any error implementing `From` for
/// this service`s `Error`.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn from_err<E>(self) -> FromErr<Self, E>
where
Self: Sized,
@ -72,11 +99,11 @@ pub trait ServiceExt<Request>: Service<Request> {
FromErr::new(self)
}
// /// Chain on a computation for when a call to the service finished,
// /// passing the result of the call to the next service `B`.
// ///
// /// Note that this function consumes the receiving future and returns a
// /// wrapped version of it.
/// Chain on a computation for when a call to the service finished,
/// passing the result of the call to the next service `B`.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn then<B>(self, service: B) -> Then<Self, B>
where
Self: Sized,
@ -85,15 +112,15 @@ pub trait ServiceExt<Request>: Service<Request> {
Then::new(self, service)
}
// /// Map this service's output to a different type, returning a new service
// /// of the resulting type.
// ///
// /// This function is similar to the `Option::map` or `Iterator::map` where
// /// it will change the type of the underlying service.
// ///
// /// Note that this function consumes the receiving service and returns a
// /// wrapped version of it, similar to the existing `map` methods in the
// /// standard library.
/// Map this service's output to a different type, returning a new service
/// of the resulting type.
///
/// This function is similar to the `Option::map` or `Iterator::map` where
/// it will change the type of the underlying service.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it, similar to the existing `map` methods in the
/// standard library.
fn map<F, R>(self, f: F) -> Map<Self, F, R>
where
Self: Sized,
@ -102,14 +129,14 @@ pub trait ServiceExt<Request>: Service<Request> {
Map::new(self, f)
}
// /// Map this service's error to a different error, returning a new service.
// ///
// /// This function is similar to the `Result::map_err` where it will change
// /// the error type of the underlying service. This is useful for example to
// /// ensure that services have the same error type.
// ///
// /// Note that this function consumes the receiving service and returns a
// /// wrapped version of it.
/// Map this service's error to a different error, returning a new service.
///
/// This function is similar to the `Result::map_err` where it will change
/// the error type of the underlying service. This is useful for example to
/// ensure that services have the same error type.
///
/// Note that this function consumes the receiving service and returns a
/// wrapped version of it.
fn map_err<F, E>(self, f: F) -> MapErr<Self, F, E>
where
Self: Sized,
@ -146,9 +173,9 @@ pub trait NewService<Request> {
/// Create and return a new service value asynchronously.
fn new_service(&self) -> Self::Future;
}
pub trait NewServiceExt<Request>: NewService<Request> {
/// Apply function to specified service and use it as a next service in
/// chain.
fn apply<T, I, F, Out, Req>(
self,
service: I,
@ -156,7 +183,7 @@ pub trait NewServiceExt<Request>: NewService<Request> {
) -> AndThenNewService<Self, ApplyNewService<T, F, Self::Response, Out, Req>>
where
Self: Sized,
T: NewService<Req, InitError = Self::InitError, Error = Out::Error>,
T: NewService<Req, InitError = Self::InitError, Error = Self::Error>,
I: IntoNewService<T, Req>,
F: Fn(Self::Response, &mut T::Service) -> Out + Clone,
Out: IntoFuture<Error = Self::Error>,
@ -164,6 +191,7 @@ pub trait NewServiceExt<Request>: NewService<Request> {
self.and_then(ApplyNewService::new(service, f))
}
/// Call another service after call to this one has resolved successfully.
fn and_then<F, B>(self, new_service: F) -> AndThenNewService<Self, B>
where
Self: Sized,
@ -173,12 +201,12 @@ pub trait NewServiceExt<Request>: NewService<Request> {
AndThenNewService::new(self, new_service)
}
// /// `NewService` that create service to map this service's error
// /// and new service's init error to any error
// /// implementing `From` for this service`s `Error`.
// ///
// /// Note that this function consumes the receiving new service and returns a
// /// wrapped version of it.
/// `NewService` that create service to map this service's error
/// and new service's init error to any error
/// implementing `From` for this service`s `Error`.
///
/// Note that this function consumes the receiving new service and returns a
/// wrapped version of it.
fn from_err<E>(self) -> FromErrNewService<Self, E>
where
Self: Sized,
@ -187,12 +215,12 @@ pub trait NewServiceExt<Request>: NewService<Request> {
FromErrNewService::new(self)
}
// /// Create `NewService` to chain on a computation for when a call to the
// /// service finished, passing the result of the call to the next
// /// service `B`.
// ///
// /// Note that this function consumes the receiving future and returns a
// /// wrapped version of it.
/// Create `NewService` to chain on a computation for when a call to the
/// service finished, passing the result of the call to the next
/// service `B`.
///
/// Note that this function consumes the receiving future and returns a
/// wrapped version of it.
fn then<F, B>(self, new_service: F) -> ThenNewService<Self, B>
where
Self: Sized,
@ -206,6 +234,8 @@ pub trait NewServiceExt<Request>: NewService<Request> {
ThenNewService::new(self, new_service)
}
/// Map this service's output to a different type, returning a new service
/// of the resulting type.
fn map<F, R>(self, f: F) -> MapNewService<Self, F, R>
where
Self: Sized,
@ -214,6 +244,7 @@ pub trait NewServiceExt<Request>: NewService<Request> {
MapNewService::new(self, f)
}
/// Map this service's error to a different error, returning a new service.
fn map_err<F, E>(self, f: F) -> MapErrNewService<Self, F, E>
where
Self: Sized,
@ -222,6 +253,7 @@ pub trait NewServiceExt<Request>: NewService<Request> {
MapErrNewService::new(self, f)
}
/// Map this service's init error to a different error, returning a new service.
fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, E>
where
Self: Sized,
@ -231,6 +263,23 @@ pub trait NewServiceExt<Request>: NewService<Request> {
}
}
impl<'a, S, Request> Service<Request> for &'a mut S
where
S: Service<Request> + 'a,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self) -> Poll<(), S::Error> {
(**self).poll_ready()
}
fn call(&mut self, request: Request) -> S::Future {
(**self).call(request)
}
}
impl<F, R, E, S, Request> NewService<Request> for F
where
F: Fn() -> R,
@ -248,9 +297,6 @@ where
}
}
impl<T: ?Sized, R> ServiceExt<R> for T where T: Service<R> {}
impl<T: ?Sized, R> NewServiceExt<R> for T where T: NewService<R> {}
/// Trait for types that can be converted to a `Service`
pub trait IntoService<T, Request>
where

View file

@ -189,7 +189,7 @@ mod tests {
use futures::future::{ok, FutureResult};
use super::*;
use crate::service::{IntoNewService, NewServiceExt, Service, ServiceExt};
use crate::{IntoNewService, Service};
struct Srv;
impl Service<()> for Srv {

View file

@ -190,7 +190,7 @@ mod tests {
use futures::future::{err, FutureResult};
use super::*;
use crate::service::{IntoNewService, NewServiceExt, Service, ServiceExt};
use crate::{IntoNewService, NewService, Service};
struct Srv;

View file

@ -46,7 +46,7 @@ where
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
try_ready!(self.a.poll_ready());
self.b.borrow_mut().poll_ready()
self.b.get_mut().poll_ready()
}
fn call(&mut self, req: Request) -> Self::Future {
@ -93,11 +93,11 @@ where
match self.fut_a.poll() {
Ok(Async::Ready(resp)) => {
self.fut_b = Some(self.b.borrow_mut().call(Ok(resp)));
self.fut_b = Some(self.b.get_mut().call(Ok(resp)));
self.poll()
}
Err(err) => {
self.fut_b = Some(self.b.borrow_mut().call(Err(err)));
self.fut_b = Some(self.b.get_mut().call(Err(err)));
self.poll()
}
Ok(Async::NotReady) => Ok(Async::NotReady),
@ -226,7 +226,6 @@ mod tests {
use std::rc::Rc;
use super::*;
use crate::service::{NewServiceExt, ServiceExt};
#[derive(Clone)]
struct Srv1(Rc<Cell<usize>>);

View file

@ -23,7 +23,6 @@ pub mod inflight;
pub mod keepalive;
pub mod resolver;
pub mod server;
pub mod service;
pub mod ssl;
pub mod stream;
pub mod time;