-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
filter: expose predicate check as methods on Filter
and AsyncFilter
#521
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Motivation ---------- In Linkerd 2, we have our own `RequestFilter` middleware. Now that Tower 0.4 has been released, including a new synchronous request filtering middleware, we'd like to migrate to Tower's filter middleware. However, there's one hitch: we implement additional traits for our filtering middleware --- in particular, we use a `NewService` trait, which is essentially a synchronous version of `MakeService`, for services that can be constructed immediately. We'd like to be able to implement that trait for `tower::filter::Filter` services as well. Solution -------- This branch adds new `Filter::check` and `AsyncFilter::check` methods which expose the inner `Predicate::check` and `AsyncPredicate::check` methods on the filter service's predicate. This can be used to call into the predicate directly, allowing external traits to be implemented for `Filter`/`AsyncFilter` in downstream code. Of course, the additional traits must be defined in the crate providing implementaitons for `tower::filter`, since `Filter` and `AsyncFilter` would be foreign types, but in our use case, at least, this isn't an issue.
LucioFranco
approved these changes
Jan 11, 2021
tower/src/filter/mod.rs
Outdated
@@ -72,6 +72,14 @@ impl<T, U> Filter<T, U> { | |||
pub fn layer(predicate: U) -> FilterLayer<U> { | |||
FilterLayer::new(predicate) | |||
} | |||
|
|||
/// Check a `Request` value against this filter's predicate. | |||
pub fn check<Request>(&mut self, request: Request) -> Result<U::Request, BoxError> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only nit I have is we have a lot of Request
in here, maybe change the generic to be R
?
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
…r into eliza/expose-filter-checks
hawkw
added a commit
that referenced
this pull request
Jan 11, 2021
This branch adds methods to access the inner service of a `Filter` or an `AsyncFilter`. These are identical to the similarly-named method provided by many other middleware services. Along with the changes in #521, this is also necessary to implement filtered versions of foreign traits in downstream code. I probably should've added this in that PR, but I wasn't thinking it through...
hawkw
added a commit
that referenced
this pull request
Jan 11, 2021
This branch adds methods to access the inner service of a `Filter` or an `AsyncFilter`. These are identical to the similarly-named method provided by many other middleware services. Along with the changes in #521, this is also necessary to implement filtered versions of foreign traits in downstream code. I probably should've added this in that PR, but I wasn't thinking it through...
olix0r
pushed a commit
to linkerd/linkerd2-proxy
that referenced
this pull request
Jan 14, 2021
Tower provides a `tower::filter` utility for conditionally rejecting some requests and accepting others. Rather than using `tower`'s filter, we have a similar `linkerd_stack::request_filter`, due to two main issues with the filtering API in tower 0.3 and earlier: * `tower::filter`'s predicates returned futures, which we don't need --- all our filtering predicates are purely sunchronous * `tower::filter` didn't allow filters to return any error of their choosing --- they had to return a specific filter-rejected error. This doesn't work with other code where we downcast error types, like switch/fallback. However, Tower 0.4 includes a rewritten `Filter` API that no longer has these issues (tower-rs/tower#508). Therefore, we can switch to using the upstream implementation. This branch replaces `RequestFilter` with `tower::filter::Filter`. It was necessary to add an impl of `NewService` for `Filter`. This required an upstream change to expose access to the wrapped service, so that its `new_service` method can be called when it's a `NewService`, and to expose access to the `Predicate`. Therefore, this PR depends on tower-rs/tower#521 and tower-rs/tower#522, and introduces a Git dependency. The git dep can be removed when Tower 0.4.3 is released. Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
In Linkerd 2, we have our own
RequestFilter
middleware. Now that Tower0.4 has been released, including a new synchronous request filtering
middleware, we'd like to migrate to Tower's filter middleware. However,
there's one hitch: we implement additional traits for our filtering
middleware --- in particular, we use a
NewService
trait, which isessentially a synchronous version of
MakeService
, for services thatcan be constructed immediately. We'd like to be able to implement that
trait for
tower::filter::Filter
services as well.Solution
This branch adds new
Filter::check
andAsyncFilter::check
methodswhich expose the inner
Predicate::check
andAsyncPredicate::check
methods on the filter service's predicate. This can be used to call into
the predicate directly, allowing external traits to be implemented for
Filter
/AsyncFilter
in downstream code. Of course, the additionaltraits must be defined in the crate providing implementaitons for
tower::filter
, sinceFilter
andAsyncFilter
would be foreigntypes, but in our use case, at least, this isn't an issue.