tower/filter/
mod.rs

1//! Conditionally dispatch requests to the inner service based on the result of
2//! a predicate.
3//!
4//! A predicate takes some request type and returns a `Result<Request, Error>`.
5//! If the predicate returns [`Ok`], the inner service is called with the request
6//! returned by the predicate &mdash; which may be the original request or a
7//! modified one. If the predicate returns [`Err`], the request is rejected and
8//! the inner service is not called.
9//!
10//! Predicates may either be synchronous (simple functions from a `Request` to
11//! a [`Result`]) or asynchronous (functions returning [`Future`]s). Separate
12//! traits, [`Predicate`] and [`AsyncPredicate`], represent these two types of
13//! predicate. Note that when it is not necessary to await some other
14//! asynchronous operation in the predicate, the synchronous predicate should be
15//! preferred, as it introduces less overhead.
16//!
17//! The predicate traits are implemented for closures and function pointers.
18//! However, users may also implement them for other types, such as when the
19//! predicate requires some state carried between requests. For example,
20//! [`Predicate`] could be implemented for a type that rejects a fixed set of
21//! requests by checking if they are contained by a a [`HashSet`] or other
22//! collection.
23//!
24//! [`Future`]: std::future::Future
25//! [`HashSet`]: std::collections::HashSet
26pub mod future;
27mod layer;
28mod predicate;
29
30pub use self::{
31    layer::{AsyncFilterLayer, FilterLayer},
32    predicate::{AsyncPredicate, Predicate},
33};
34
35use self::future::{AsyncResponseFuture, ResponseFuture};
36use crate::BoxError;
37use futures_util::{future::Either, TryFutureExt};
38use std::task::{Context, Poll};
39use tower_service::Service;
40
41/// Conditionally dispatch requests to the inner service based on a [predicate].
42///
43/// [predicate]: Predicate
44#[derive(Clone, Debug)]
45pub struct Filter<T, U> {
46    inner: T,
47    predicate: U,
48}
49
50/// Conditionally dispatch requests to the inner service based on an
51/// [asynchronous predicate].
52///
53/// [asynchronous predicate]: AsyncPredicate
54#[derive(Clone, Debug)]
55pub struct AsyncFilter<T, U> {
56    inner: T,
57    predicate: U,
58}
59
60// ==== impl Filter ====
61
62impl<T, U> Filter<T, U> {
63    /// Returns a new [`Filter`] service wrapping `inner`.
64    pub const fn new(inner: T, predicate: U) -> Self {
65        Self { inner, predicate }
66    }
67
68    /// Returns a new [`Layer`] that wraps services with a [`Filter`] service
69    /// with the given [`Predicate`].
70    ///
71    /// [`Layer`]: crate::Layer
72    pub fn layer(predicate: U) -> FilterLayer<U> {
73        FilterLayer::new(predicate)
74    }
75
76    /// Check a `Request` value against this filter's predicate.
77    pub fn check<R>(&mut self, request: R) -> Result<U::Request, BoxError>
78    where
79        U: Predicate<R>,
80    {
81        self.predicate.check(request)
82    }
83
84    /// Get a reference to the inner service
85    pub fn get_ref(&self) -> &T {
86        &self.inner
87    }
88
89    /// Get a mutable reference to the inner service
90    pub fn get_mut(&mut self) -> &mut T {
91        &mut self.inner
92    }
93
94    /// Consume `self`, returning the inner service
95    pub fn into_inner(self) -> T {
96        self.inner
97    }
98}
99
100impl<T, U, Request> Service<Request> for Filter<T, U>
101where
102    U: Predicate<Request>,
103    T: Service<U::Request>,
104    T::Error: Into<BoxError>,
105{
106    type Response = T::Response;
107    type Error = BoxError;
108    type Future = ResponseFuture<T::Response, T::Future>;
109
110    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
111        self.inner.poll_ready(cx).map_err(Into::into)
112    }
113
114    fn call(&mut self, request: Request) -> Self::Future {
115        ResponseFuture::new(match self.predicate.check(request) {
116            Ok(request) => Either::Right(self.inner.call(request).err_into()),
117            Err(e) => Either::Left(futures_util::future::ready(Err(e))),
118        })
119    }
120}
121
122// ==== impl AsyncFilter ====
123
124impl<T, U> AsyncFilter<T, U> {
125    /// Returns a new [`AsyncFilter`] service wrapping `inner`.
126    pub const fn new(inner: T, predicate: U) -> Self {
127        Self { inner, predicate }
128    }
129
130    /// Returns a new [`Layer`] that wraps services with an [`AsyncFilter`]
131    /// service with the given [`AsyncPredicate`].
132    ///
133    /// [`Layer`]: crate::Layer
134    pub fn layer(predicate: U) -> FilterLayer<U> {
135        FilterLayer::new(predicate)
136    }
137
138    /// Check a `Request` value against this filter's predicate.
139    pub async fn check<R>(&mut self, request: R) -> Result<U::Request, BoxError>
140    where
141        U: AsyncPredicate<R>,
142    {
143        self.predicate.check(request).await
144    }
145
146    /// Get a reference to the inner service
147    pub fn get_ref(&self) -> &T {
148        &self.inner
149    }
150
151    /// Get a mutable reference to the inner service
152    pub fn get_mut(&mut self) -> &mut T {
153        &mut self.inner
154    }
155
156    /// Consume `self`, returning the inner service
157    pub fn into_inner(self) -> T {
158        self.inner
159    }
160}
161
162impl<T, U, Request> Service<Request> for AsyncFilter<T, U>
163where
164    U: AsyncPredicate<Request>,
165    T: Service<U::Request> + Clone,
166    T::Error: Into<BoxError>,
167{
168    type Response = T::Response;
169    type Error = BoxError;
170    type Future = AsyncResponseFuture<U, T, Request>;
171
172    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
173        self.inner.poll_ready(cx).map_err(Into::into)
174    }
175
176    fn call(&mut self, request: Request) -> Self::Future {
177        use std::mem;
178
179        let inner = self.inner.clone();
180        // In case the inner service has state that's driven to readiness and
181        // not tracked by clones (such as `Buffer`), pass the version we have
182        // already called `poll_ready` on into the future, and leave its clone
183        // behind.
184        let inner = mem::replace(&mut self.inner, inner);
185
186        // Check the request
187        let check = self.predicate.check(request);
188
189        AsyncResponseFuture::new(check, inner)
190    }
191}