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 — 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}