mirror of
https://github.com/Noratrieb/101844-repro.git
synced 2026-01-16 15:15:00 +01:00
only tower
This commit is contained in:
parent
fa88e78ef7
commit
64cabb2240
24 changed files with 22 additions and 770 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -162,19 +162,9 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-layer"
|
|
||||||
version = "0.3.1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-service"
|
|
||||||
version = "0.3.2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.36"
|
version = "0.1.36"
|
||||||
|
|
|
||||||
2
tower/.gitignore
vendored
2
tower/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
target
|
|
||||||
Cargo.lock
|
|
||||||
|
|
@ -2,7 +2,4 @@
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"tower",
|
"tower",
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tower-test",
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
Copyright (c) 2019 Tower Contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
|
||||||
person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the
|
|
||||||
Software without restriction, including without
|
|
||||||
limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software
|
|
||||||
is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice
|
|
||||||
shall be included in all copies or substantial portions
|
|
||||||
of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
||||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
# Tower
|
|
||||||
|
|
||||||
Tower is a library of modular and reusable components for building robust
|
|
||||||
networking clients and servers.
|
|
||||||
|
|
||||||
[![Crates.io][crates-badge]][crates-url]
|
|
||||||
[![Documentation][docs-badge]][docs-url]
|
|
||||||
[![Documentation (master)][docs-master-badge]][docs-master-url]
|
|
||||||
[![MIT licensed][mit-badge]][mit-url]
|
|
||||||
[![Build Status][actions-badge]][actions-url]
|
|
||||||
[![Discord chat][discord-badge]][discord-url]
|
|
||||||
|
|
||||||
[crates-badge]: https://img.shields.io/crates/v/tower.svg
|
|
||||||
[crates-url]: https://crates.io/crates/tower
|
|
||||||
[docs-badge]: https://docs.rs/tower/badge.svg
|
|
||||||
[docs-url]: https://docs.rs/tower
|
|
||||||
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
|
|
||||||
[docs-master-url]: https://tower-rs.github.io/tower/tower
|
|
||||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
||||||
[mit-url]: LICENSE
|
|
||||||
[actions-badge]: https://github.com/tower-rs/tower/workflows/CI/badge.svg
|
|
||||||
[actions-url]:https://github.com/tower-rs/tower/actions?query=workflow%3ACI
|
|
||||||
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
|
|
||||||
[discord-url]: https://discord.gg/EeF3cQw
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Tower aims to make it as easy as possible to build robust networking clients and
|
|
||||||
servers. It is protocol agnostic, but is designed around a request / response
|
|
||||||
pattern. If your protocol is entirely stream based, Tower may not be a good fit.
|
|
||||||
|
|
||||||
## Supported Rust Versions
|
|
||||||
|
|
||||||
Tower will keep a rolling MSRV (minimum supported Rust version) policy of **at
|
|
||||||
least** 6 months. When increasing the MSRV, the new Rust version must have been
|
|
||||||
released at least six months ago. The current MSRV is 1.49.0.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
If you're brand new to Tower and want to start with the basics we recommend you
|
|
||||||
check out some of our [guides].
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the [MIT license](LICENSE).
|
|
||||||
|
|
||||||
### Contribution
|
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
||||||
for inclusion in Tower by you, shall be licensed as MIT, without any additional
|
|
||||||
terms or conditions.
|
|
||||||
|
|
||||||
[guides]: https://github.com/tower-rs/tower/tree/master/guides
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
[advisories]
|
|
||||||
vulnerability = "deny"
|
|
||||||
unmaintained = "warn"
|
|
||||||
notice = "warn"
|
|
||||||
ignore = ["RUSTSEC-2020-0159"]
|
|
||||||
|
|
||||||
[licenses]
|
|
||||||
unlicensed = "deny"
|
|
||||||
allow = []
|
|
||||||
deny = []
|
|
||||||
copyleft = "warn"
|
|
||||||
allow-osi-fsf-free = "either"
|
|
||||||
confidence-threshold = 0.8
|
|
||||||
|
|
||||||
[bans]
|
|
||||||
multiple-versions = "deny"
|
|
||||||
highlight = "all"
|
|
||||||
skip = []
|
|
||||||
|
|
||||||
[sources]
|
|
||||||
unknown-registry = "warn"
|
|
||||||
unknown-git = "warn"
|
|
||||||
allow-git = []
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
[build]
|
|
||||||
command = "rustup install nightly --profile minimal && cargo doc --features=full --no-deps && cp -r target/doc _netlify_out"
|
|
||||||
environment = { RUSTDOCFLAGS= "--cfg docsrs" }
|
|
||||||
publish = "_netlify_out"
|
|
||||||
|
|
||||||
[[redirects]]
|
|
||||||
from = "/"
|
|
||||||
to = "/tower"
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
# 0.3.1 (January 7, 2021)
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Added `layer_fn`, for constructing a `Layer` from a function taking
|
|
||||||
a `Service` and returning a different `Service` ([#491])
|
|
||||||
- Added an implementation of `Layer` for `&Layer` ([#446])
|
|
||||||
- Multiple documentation improvements ([#487], [#490])
|
|
||||||
|
|
||||||
[#491]: https://github.com/tower-rs/tower/pull/491
|
|
||||||
[#446]: https://github.com/tower-rs/tower/pull/446
|
|
||||||
[#487]: https://github.com/tower-rs/tower/pull/487
|
|
||||||
[#490]: https://github.com/tower-rs/tower/pull/490
|
|
||||||
|
|
||||||
# 0.3.0 (November 29, 2019)
|
|
||||||
|
|
||||||
- Move layer builder from `tower-util` to tower-layer.
|
|
||||||
|
|
||||||
# 0.3.0-alpha.2 (September 30, 2019)
|
|
||||||
|
|
||||||
- Move to `futures-*-preview 0.3.0-alpha.19`
|
|
||||||
- Move to `pin-project 0.4`
|
|
||||||
|
|
||||||
# 0.3.0-alpha.1 (September 11, 2019)
|
|
||||||
|
|
||||||
- Move to `std::future`
|
|
||||||
|
|
||||||
# 0.1.0 (April 26, 2019)
|
|
||||||
|
|
||||||
- Initial release
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "tower-layer"
|
|
||||||
# When releasing to crates.io:
|
|
||||||
# - Update doc url
|
|
||||||
# - Cargo.toml
|
|
||||||
# - README.md
|
|
||||||
# - Update CHANGELOG.md.
|
|
||||||
# - Create "v0.1.x" git tag.
|
|
||||||
version = "0.3.1"
|
|
||||||
authors = ["Tower Maintainers <team@tower-rs.com>"]
|
|
||||||
license = "MIT"
|
|
||||||
readme = "README.md"
|
|
||||||
repository = "https://github.com/tower-rs/tower"
|
|
||||||
homepage = "https://github.com/tower-rs/tower"
|
|
||||||
documentation = "https://docs.rs/tower-layer/0.3.0-alpha.2"
|
|
||||||
description = """
|
|
||||||
Decorates a `Service` to allow easy composition between `Service`s.
|
|
||||||
"""
|
|
||||||
categories = ["asynchronous", "network-programming"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tower-service = { version = "0.3.0", path = "../tower-service" }
|
|
||||||
tower = { version = "0.4", path = "../tower" }
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
Copyright (c) 2019 Tower Contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
|
||||||
person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the
|
|
||||||
Software without restriction, including without
|
|
||||||
limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software
|
|
||||||
is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice
|
|
||||||
shall be included in all copies or substantial portions
|
|
||||||
of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
||||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
# Tower Layer
|
|
||||||
|
|
||||||
Decorates a [Tower] `Service`, transforming either the request or the response.
|
|
||||||
|
|
||||||
[![Crates.io][crates-badge]][crates-url]
|
|
||||||
[![Documentation][docs-badge]][docs-url]
|
|
||||||
[![Documentation (master)][docs-master-badge]][docs-master-url]
|
|
||||||
[![MIT licensed][mit-badge]][mit-url]
|
|
||||||
[![Build Status][actions-badge]][actions-url]
|
|
||||||
[![Discord chat][discord-badge]][discord-url]
|
|
||||||
|
|
||||||
[crates-badge]: https://img.shields.io/crates/v/tower-layer.svg
|
|
||||||
[crates-url]: https://crates.io/crates/tower-layer
|
|
||||||
[docs-badge]: https://docs.rs/tower-layer/badge.svg
|
|
||||||
[docs-url]: https://docs.rs/tower-layer
|
|
||||||
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
|
|
||||||
[docs-master-url]: https://tower-rs.github.io/tower/tower_layer
|
|
||||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
||||||
[mit-url]: LICENSE
|
|
||||||
[actions-badge]: https://github.com/tower-rs/tower/workflows/CI/badge.svg
|
|
||||||
[actions-url]:https://github.com/tower-rs/tower/actions?query=workflow%3ACI
|
|
||||||
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
|
|
||||||
[discord-url]: https://discord.gg/EeF3cQw
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Often, many of the pieces needed for writing network applications can be
|
|
||||||
reused across multiple services. The `Layer` trait can be used to write
|
|
||||||
reusable components that can be applied to very different kinds of services;
|
|
||||||
for example, it can be applied to services operating on different protocols,
|
|
||||||
and to both the client and server side of a network transaction.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the [MIT license](LICENSE).
|
|
||||||
|
|
||||||
### Contribution
|
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
||||||
for inclusion in Tower by you, shall be licensed as MIT, without any additional
|
|
||||||
terms or conditions.
|
|
||||||
|
|
||||||
[Tower]: https://crates.io/crates/tower
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
use super::Layer;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
/// A no-op middleware.
|
|
||||||
///
|
|
||||||
/// When wrapping a [`Service`], the [`Identity`] layer returns the provided
|
|
||||||
/// service without modifying it.
|
|
||||||
///
|
|
||||||
/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
pub struct Identity {
|
|
||||||
_p: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Identity {
|
|
||||||
/// Create a new [`Identity`] value
|
|
||||||
pub fn new() -> Identity {
|
|
||||||
Identity { _p: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decorates a [`Service`], transforming either the request or the response.
|
|
||||||
///
|
|
||||||
/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
|
|
||||||
impl<S> Layer<S> for Identity {
|
|
||||||
type Service = S;
|
|
||||||
|
|
||||||
fn layer(&self, inner: S) -> Self::Service {
|
|
||||||
inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Identity {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_struct("Identity").finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
use super::Layer;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
/// Returns a new [`LayerFn`] that implements [`Layer`] by calling the
|
|
||||||
/// given function.
|
|
||||||
///
|
|
||||||
/// The [`Layer::layer`] method takes a type implementing [`Service`] and
|
|
||||||
/// returns a different type implementing [`Service`]. In many cases, this can
|
|
||||||
/// be implemented by a function or a closure. The [`LayerFn`] helper allows
|
|
||||||
/// writing simple [`Layer`] implementations without needing the boilerplate of
|
|
||||||
/// a new struct implementing [`Layer`].
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
/// ```rust
|
|
||||||
/// # use tower::Service;
|
|
||||||
/// # use std::task::{Poll, Context};
|
|
||||||
/// # use tower_layer::{Layer, layer_fn};
|
|
||||||
/// # use std::fmt;
|
|
||||||
/// # use std::convert::Infallible;
|
|
||||||
/// #
|
|
||||||
/// // A middleware that logs requests before forwarding them to another service
|
|
||||||
/// pub struct LogService<S> {
|
|
||||||
/// target: &'static str,
|
|
||||||
/// service: S,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl<S, Request> Service<Request> for LogService<S>
|
|
||||||
/// where
|
|
||||||
/// S: Service<Request>,
|
|
||||||
/// Request: fmt::Debug,
|
|
||||||
/// {
|
|
||||||
/// type Response = S::Response;
|
|
||||||
/// type Error = S::Error;
|
|
||||||
/// type Future = S::Future;
|
|
||||||
///
|
|
||||||
/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
/// self.service.poll_ready(cx)
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn call(&mut self, request: Request) -> Self::Future {
|
|
||||||
/// // Log the request
|
|
||||||
/// println!("request = {:?}, target = {:?}", request, self.target);
|
|
||||||
///
|
|
||||||
/// self.service.call(request)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // A `Layer` that wraps services in `LogService`
|
|
||||||
/// let log_layer = layer_fn(|service| {
|
|
||||||
/// LogService {
|
|
||||||
/// service,
|
|
||||||
/// target: "tower-docs",
|
|
||||||
/// }
|
|
||||||
/// });
|
|
||||||
///
|
|
||||||
/// // An example service. This one uppercases strings
|
|
||||||
/// let uppercase_service = tower::service_fn(|request: String| async move {
|
|
||||||
/// Ok::<_, Infallible>(request.to_uppercase())
|
|
||||||
/// });
|
|
||||||
///
|
|
||||||
/// // Wrap our service in a `LogService` so requests are logged.
|
|
||||||
/// let wrapped_service = log_layer.layer(uppercase_service);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
|
|
||||||
/// [`Layer::layer`]: crate::Layer::layer
|
|
||||||
pub fn layer_fn<T>(f: T) -> LayerFn<T> {
|
|
||||||
LayerFn { f }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A `Layer` implemented by a closure. See the docs for [`layer_fn`] for more details.
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct LayerFn<F> {
|
|
||||||
f: F,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F, S, Out> Layer<S> for LayerFn<F>
|
|
||||||
where
|
|
||||||
F: Fn(S) -> Out,
|
|
||||||
{
|
|
||||||
type Service = Out;
|
|
||||||
|
|
||||||
fn layer(&self, inner: S) -> Self::Service {
|
|
||||||
(self.f)(inner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> fmt::Debug for LayerFn<F> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_struct("LayerFn")
|
|
||||||
.field("f", &format_args!("{}", std::any::type_name::<F>()))
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[test]
|
|
||||||
fn layer_fn_has_useful_debug_impl() {
|
|
||||||
struct WrappedService<S> {
|
|
||||||
inner: S,
|
|
||||||
}
|
|
||||||
let layer = layer_fn(|svc| WrappedService { inner: svc });
|
|
||||||
let _svc = layer.layer("foo");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
"LayerFn { f: tower_layer::layer_fn::tests::layer_fn_has_useful_debug_impl::{{closure}} }".to_string(),
|
|
||||||
format!("{:?}", layer),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
#![warn(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
rust_2018_idioms,
|
|
||||||
unreachable_pub
|
|
||||||
)]
|
|
||||||
#![forbid(unsafe_code)]
|
|
||||||
// `rustdoc::broken_intra_doc_links` is checked on CI
|
|
||||||
|
|
||||||
//! Layer traits and extensions.
|
|
||||||
//!
|
|
||||||
//! A layer decorates an service and provides additional functionality. It
|
|
||||||
//! allows other services to be composed with the service that implements layer.
|
|
||||||
//!
|
|
||||||
//! A middleware implements the [`Layer`] and [`Service`] trait.
|
|
||||||
//!
|
|
||||||
//! [`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
|
|
||||||
|
|
||||||
mod identity;
|
|
||||||
mod layer_fn;
|
|
||||||
mod stack;
|
|
||||||
|
|
||||||
pub use self::{
|
|
||||||
identity::Identity,
|
|
||||||
layer_fn::{layer_fn, LayerFn},
|
|
||||||
stack::Stack,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Decorates a [`Service`], transforming either the request or the response.
|
|
||||||
///
|
|
||||||
/// Often, many of the pieces needed for writing network applications can be
|
|
||||||
/// reused across multiple services. The `Layer` trait can be used to write
|
|
||||||
/// reusable components that can be applied to very different kinds of services;
|
|
||||||
/// for example, it can be applied to services operating on different protocols,
|
|
||||||
/// and to both the client and server side of a network transaction.
|
|
||||||
///
|
|
||||||
/// # Log
|
|
||||||
///
|
|
||||||
/// Take request logging as an example:
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # use tower_service::Service;
|
|
||||||
/// # use std::task::{Poll, Context};
|
|
||||||
/// # use tower_layer::Layer;
|
|
||||||
/// # use std::fmt;
|
|
||||||
///
|
|
||||||
/// pub struct LogLayer {
|
|
||||||
/// target: &'static str,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl<S> Layer<S> for LogLayer {
|
|
||||||
/// type Service = LogService<S>;
|
|
||||||
///
|
|
||||||
/// fn layer(&self, service: S) -> Self::Service {
|
|
||||||
/// LogService {
|
|
||||||
/// target: self.target,
|
|
||||||
/// service
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // This service implements the Log behavior
|
|
||||||
/// pub struct LogService<S> {
|
|
||||||
/// target: &'static str,
|
|
||||||
/// service: S,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl<S, Request> Service<Request> for LogService<S>
|
|
||||||
/// where
|
|
||||||
/// S: Service<Request>,
|
|
||||||
/// Request: fmt::Debug,
|
|
||||||
/// {
|
|
||||||
/// type Response = S::Response;
|
|
||||||
/// type Error = S::Error;
|
|
||||||
/// type Future = S::Future;
|
|
||||||
///
|
|
||||||
/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
/// self.service.poll_ready(cx)
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn call(&mut self, request: Request) -> Self::Future {
|
|
||||||
/// // Insert log statement here or other functionality
|
|
||||||
/// println!("request = {:?}, target = {:?}", request, self.target);
|
|
||||||
/// self.service.call(request)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The above log implementation is decoupled from the underlying protocol and
|
|
||||||
/// is also decoupled from client or server concerns. In other words, the same
|
|
||||||
/// log middleware could be used in either a client or a server.
|
|
||||||
///
|
|
||||||
/// [`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
|
|
||||||
pub trait Layer<S> {
|
|
||||||
/// The wrapped service
|
|
||||||
type Service;
|
|
||||||
/// Wrap the given service with the middleware, returning a new service
|
|
||||||
/// that has been decorated with the middleware.
|
|
||||||
fn layer(&self, inner: S) -> Self::Service;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, S> Layer<S> for &'a T
|
|
||||||
where
|
|
||||||
T: ?Sized + Layer<S>,
|
|
||||||
{
|
|
||||||
type Service = T::Service;
|
|
||||||
|
|
||||||
fn layer(&self, inner: S) -> Self::Service {
|
|
||||||
(**self).layer(inner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
use super::Layer;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
/// Two middlewares chained together.
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Stack<Inner, Outer> {
|
|
||||||
inner: Inner,
|
|
||||||
outer: Outer,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Inner, Outer> Stack<Inner, Outer> {
|
|
||||||
/// Create a new `Stack`.
|
|
||||||
pub fn new(inner: Inner, outer: Outer) -> Self {
|
|
||||||
Stack { inner, outer }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, Inner, Outer> Layer<S> for Stack<Inner, Outer>
|
|
||||||
where
|
|
||||||
Inner: Layer<S>,
|
|
||||||
Outer: Layer<Inner::Service>,
|
|
||||||
{
|
|
||||||
type Service = Outer::Service;
|
|
||||||
|
|
||||||
fn layer(&self, service: S) -> Self::Service {
|
|
||||||
let inner = self.inner.layer(service);
|
|
||||||
|
|
||||||
self.outer.layer(inner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Inner, Outer> fmt::Debug for Stack<Inner, Outer>
|
|
||||||
where
|
|
||||||
Inner: fmt::Debug,
|
|
||||||
Outer: fmt::Debug,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// The generated output of nested `Stack`s is very noisy and makes
|
|
||||||
// it harder to understand what is in a `ServiceBuilder`.
|
|
||||||
//
|
|
||||||
// Instead, this output is designed assuming that a `Stack` is
|
|
||||||
// usually quite nested, and inside a `ServiceBuilder`. Therefore,
|
|
||||||
// this skips using `f.debug_struct()`, since each one would force
|
|
||||||
// a new layer of indentation.
|
|
||||||
//
|
|
||||||
// - In compact mode, a nested stack ends up just looking like a flat
|
|
||||||
// list of layers.
|
|
||||||
//
|
|
||||||
// - In pretty mode, while a newline is inserted between each layer,
|
|
||||||
// the `DebugStruct` used in the `ServiceBuilder` will inject padding
|
|
||||||
// to that each line is at the same indentation level.
|
|
||||||
//
|
|
||||||
// Also, the order of [outer, inner] is important, since it reflects
|
|
||||||
// the order that the layers were added to the stack.
|
|
||||||
if f.alternate() {
|
|
||||||
// pretty
|
|
||||||
write!(f, "{:#?},\n{:#?}", self.outer, self.inner)
|
|
||||||
} else {
|
|
||||||
write!(f, "{:?}, {:?}", self.outer, self.inner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
# Unreleased
|
|
||||||
|
|
||||||
- None
|
|
||||||
|
|
||||||
# 0.3.2 (June 17, 2022)
|
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
- **docs**: Clarify subtlety around cloning and readiness in the `Service` docs
|
|
||||||
([#548])
|
|
||||||
- **docs**: Clarify details around shared resource consumption in `poll_ready()`
|
|
||||||
([#662])
|
|
||||||
|
|
||||||
|
|
||||||
[#548]: https://github.com/tower-rs/tower/pull/548
|
|
||||||
[#662]: https://github.com/tower-rs/tower/pull/662
|
|
||||||
|
|
||||||
|
|
||||||
# 0.3.1 (November 29, 2019)
|
|
||||||
|
|
||||||
- Improve example in `Service` docs. ([#510])
|
|
||||||
|
|
||||||
[#510]: https://github.com/tower-rs/tower/pull/510
|
|
||||||
|
|
||||||
# 0.3.0 (November 29, 2019)
|
|
||||||
|
|
||||||
- Update to `futures 0.3`.
|
|
||||||
- Update documentation for `std::future::Future`.
|
|
||||||
|
|
||||||
# 0.3.0-alpha.2 (September 30, 2019)
|
|
||||||
|
|
||||||
- Documentation fixes.
|
|
||||||
|
|
||||||
# 0.3.0-alpha.1 (Aug 20, 2019)
|
|
||||||
|
|
||||||
* Switch to `std::future::Future`
|
|
||||||
|
|
||||||
# 0.2.0 (Dec 12, 2018)
|
|
||||||
|
|
||||||
* Change `Service`'s `Request` associated type to be a generic instead.
|
|
||||||
* Before:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Service for Client {
|
|
||||||
type Request = HttpRequest;
|
|
||||||
type Response = HttpResponse;
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* After:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Service<HttpRequest> for Client {
|
|
||||||
type Response = HttpResponse;
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Remove `NewService`, use `tower_util::MakeService` instead.
|
|
||||||
* Remove `Service::ready` and `Ready`, use `tower_util::ServiceExt` instead.
|
|
||||||
|
|
||||||
# 0.1.0 (Aug 9, 2018)
|
|
||||||
|
|
||||||
* Initial release
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "tower-service"
|
|
||||||
# When releasing to crates.io:
|
|
||||||
# - Update doc url
|
|
||||||
# - Cargo.toml
|
|
||||||
# - README.md
|
|
||||||
# - Update CHANGELOG.md.
|
|
||||||
# - Create "v0.3.x" git tag.
|
|
||||||
version = "0.3.2"
|
|
||||||
authors = ["Tower Maintainers <team@tower-rs.com>"]
|
|
||||||
license = "MIT"
|
|
||||||
readme = "README.md"
|
|
||||||
repository = "https://github.com/tower-rs/tower"
|
|
||||||
homepage = "https://github.com/tower-rs/tower"
|
|
||||||
documentation = "https://docs.rs/tower-service/0.3.2"
|
|
||||||
description = """
|
|
||||||
Trait representing an asynchronous, request / response based, client or server.
|
|
||||||
"""
|
|
||||||
categories = ["asynchronous", "network-programming"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
http = "0.2"
|
|
||||||
tower-layer = { version = "0.3", path = "../tower-layer" }
|
|
||||||
tokio = { version = "1", features = ["macros", "time"] }
|
|
||||||
futures = "0.3"
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
Copyright (c) 2019 Tower Contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
|
||||||
person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the
|
|
||||||
Software without restriction, including without
|
|
||||||
limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software
|
|
||||||
is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice
|
|
||||||
shall be included in all copies or substantial portions
|
|
||||||
of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
||||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
# Tower Service
|
|
||||||
|
|
||||||
The foundational `Service` trait that [Tower] is based on.
|
|
||||||
|
|
||||||
[![Crates.io][crates-badge]][crates-url]
|
|
||||||
[![Documentation][docs-badge]][docs-url]
|
|
||||||
[![Documentation (master)][docs-master-badge]][docs-master-url]
|
|
||||||
[![MIT licensed][mit-badge]][mit-url]
|
|
||||||
[![Build Status][actions-badge]][actions-url]
|
|
||||||
[![Discord chat][discord-badge]][discord-url]
|
|
||||||
|
|
||||||
[crates-badge]: https://img.shields.io/crates/v/tower-service.svg
|
|
||||||
[crates-url]: https://crates.io/crates/tower-service
|
|
||||||
[docs-badge]: https://docs.rs/tower-service/badge.svg
|
|
||||||
[docs-url]: https://docs.rs/tower-service
|
|
||||||
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
|
|
||||||
[docs-master-url]: https://tower-rs.github.io/tower/tower_service
|
|
||||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
||||||
[mit-url]: LICENSE
|
|
||||||
[actions-badge]: https://github.com/tower-rs/tower/workflows/CI/badge.svg
|
|
||||||
[actions-url]:https://github.com/tower-rs/tower/actions?query=workflow%3ACI
|
|
||||||
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
|
|
||||||
[discord-url]: https://discord.gg/EeF3cQw
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The [`Service`] trait provides the foundation upon which [Tower] is built. It is a
|
|
||||||
simple, but powerful trait. At its heart, `Service` is just an asynchronous
|
|
||||||
function of request to response.
|
|
||||||
|
|
||||||
```
|
|
||||||
async fn(Request) -> Result<Response, Error>
|
|
||||||
```
|
|
||||||
|
|
||||||
Implementations of `Service` take a request, the type of which varies per
|
|
||||||
protocol, and returns a future representing the eventual completion or failure
|
|
||||||
of the response.
|
|
||||||
|
|
||||||
Services are used to represent both clients and servers. An *instance* of
|
|
||||||
`Service` is used through a client; a server *implements* `Service`.
|
|
||||||
|
|
||||||
By using standardizing the interface, middleware can be created. Middleware
|
|
||||||
*implement* `Service` by passing the request to another `Service`. The
|
|
||||||
middleware may take actions such as modify the request.
|
|
||||||
|
|
||||||
[`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
|
|
||||||
[Tower]: https://crates.io/crates/tower
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the [MIT license](LICENSE).
|
|
||||||
|
|
||||||
### Contribution
|
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
||||||
for inclusion in Tower by you, shall be licensed as MIT, without any additional
|
|
||||||
terms or conditions.
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
#![warn(rust_2018_idioms, unreachable_pub)]
|
|
||||||
#![forbid(unsafe_code)]
|
|
||||||
|
|
||||||
use std::future::Future;
|
|
||||||
use std::task::{Context, Poll};
|
|
||||||
|
|
||||||
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<Output = Result<Self::Response, Self::Error>>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
|
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future;
|
|
||||||
}
|
|
||||||
|
|
@ -66,9 +66,6 @@ timeout = ["pin-project-lite", "tokio/time"]
|
||||||
util = ["__common", "futures-util", "pin-project"]
|
util = ["__common", "futures-util", "pin-project"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tower-layer = { version = "0.3.1", path = "../tower-layer" }
|
|
||||||
tower-service = { version = "0.3.1", path = "../tower-service" }
|
|
||||||
|
|
||||||
futures-core = { version = "0.3", optional = true }
|
futures-core = { version = "0.3", optional = true }
|
||||||
futures-util = { version = "0.3", default-features = false, features = ["alloc"], optional = true }
|
futures-util = { version = "0.3", default-features = false, features = ["alloc"], optional = true }
|
||||||
hdrhistogram = { version = "7.0", optional = true, default-features = false }
|
hdrhistogram = { version = "7.0", optional = true, default-features = false }
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use std::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
use tower_service::Service;
|
use crate::Service;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
pub struct Balance<D, Req> {
|
pub struct Balance<D, Req> {
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,22 @@ mod load {
|
||||||
fn load(&self) -> Self::Metric;
|
fn load(&self) -> Self::Metric;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
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<Output = Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
|
||||||
|
|
||||||
|
fn call(&mut self, req: Request) -> Self::Future;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,12 @@ mod make_service {
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use tower_service::Service;
|
use crate::Service;
|
||||||
|
|
||||||
pub mod shared {
|
pub mod shared {
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use tower_service::Service;
|
use crate::Service;
|
||||||
|
|
||||||
pub struct Shared<S> {
|
pub struct Shared<S> {
|
||||||
service: S,
|
service: S,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue