-
Notifications
You must be signed in to change notification settings - Fork 221
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
Fast Fail for andThen-composed Endpoints does not work #978
Comments
Depending on which actions are being performed this could not be just wrong but also insecure. |
@sergeykolbasov @rpless I'm thinking maybe we could do |
I feel like this happens because |
Oh also @d-s-d what version of Finch are you using? |
@vkostyukov you mean introduce |
Sorry for omitting the version. The above was tested with 0.22.0 and 0.23.0. |
Considering the Finagle Filter, doesn't the fundamental issue remain? It does not make a difference if the decision is based on a context-object or the header itself, if both endpoints are "evaluated" even though the first one fails, the fundamental problem remains, no? |
Base on Error Accumulation, I tried something else that does not work either. Forgive me if I made some erroneous assumptions about the API here:
|
No problem. Given that we've changed to monthly releases the potential for version drift is higher, so we should probably have a template for github issues that includes this as a prompt. A Finagle Filter might let you get around this, if you can reject invalid auth headers from the filter instead from the Endpoint. You could then set something on the The intention of Error Accumulation for Product Endpoints is to determine all of the things that did not match. In the example above, we have a Product Endpoint of |
True that. Thanks for the clarification. This works if you have a general authentication mechanism. If you imagine a scenario where different endpoints use different authentication mechanisms, an authenticated client might trigger this behavior on an endpoint that he is not authenticated against. Actually, it's an authorization problem: the filter must not only authenticate, but also authorize the client. |
@sergeykolbasov Not |
It shouldn't change anything if we lift it to Try. Also, from the original
example there will be no exception at all as the authorization endpoint is
handled already.
The true fail-fast behavior means that we flatMap next endpoint over the
Output and with the current signature it's impossible.
…On Tue, 21 Aug 2018 at 17.24, Vladimir Kostyukov ***@***.***> wrote:
@sergeykolbasov <https://github.com/sergeykolbasov> Not Endpoint.apply,
but use Rerunnable.flatMap instead of Rerunnable.product here
<https://github.com/finagle/finch/blob/master/core/src/main/scala/io/finch/Endpoint.scala#L182>.
This will get us the fail-fast semantic monads have.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#978 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACNbQX4A2uTcIvtCeEiUphTJnDK4XUgLks5uTBgugaJpZM4WEQuc>
.
|
We still should be able to implement val ab = param[Int]("a") :: param("b") With an empty request, this will fail with I'm no longer sure it something that's easy to fix. Perhaps an alternative approach would be to promote a different way of doing an auth? |
Instead of having something specific for authentication, could we have a short-circuiting variant of I’m afraid it would still be easy to make a mistake. And we shouldn’t have to many operators. (Like sbt of yesteryear.) |
Yeah, I'm not a huge fan of adding a specific combinator for this. I'd rather see us standardizing on either fail-fast of collect-errors approach. The later has been our default for quite a long time yet I'm starting to gain some skepticism around how important it is to accumulate those errors. It may be that people just use Perpahs asking what's people's most popular use case would be a good way forward here. Maybe @rpless has some insights on where or not the error accumulation is useful in |
I'm not a big fan of combinator either. As for whether error accumulation is useful, I am a heavy user of error accumulation especially in conjunction with |
I feel that it should be the way how it's now with |
Maybe the obvious solution would be to structure finch-oauth2 (and, perhaps, other auth packages) differently? One idea is to move the auth logic somewhere under the derived service ( A sketch (enable auth on per-endpoint basis) Bootstrap
.serveSecured(Endpoint.const("fooo"), OAuth2Scheme(dataHandler)) Or per Bootstrap
.configure(authScheme = OAuth2Scheme(dataHandler)) I like the later more as we don't have to introduce I'm not in love with the fact there are now two places where users would have to "enable" auth, but I surely buy this as an ad-hoc solution until we figure out a better way. |
@vkostyukov my another thought is to introduce new type I think it should give a transparency over the request execution. |
For what it's worth, I think the lack of a way of effectively flatMapping over endpoints is a huge drawback to using Finch, currently. If there's no way to reproduce that semantic behavior, which after looking at the source code in-depth I agree with @sergeykolbasov , I think the documentation around @vkostyukov I agree that adding a bunch of combinators could be undesirable, but I think the current state is borderline untenable. If people admit the utility of monadic composition and applicative composition in general purpose FP programming, I think one should admit the utility of those patterns when composing endpoints in Finch. As of right now I think that it's sort of an impedance mismatch between how people would typically want to work with Finch and what is permitted by the library. If we don't want to add a new combinator I think there should at least be some kind of escape hatch that allows the user to reproduce these semantics, perhaps in a 'hackier' way than would be desired, but that doesn't subvert the goals of the project. It's nice to have well designed, "type-ful" interfaces to solve complex problems with, and in that respect I think Finch is a tremendous success, but I also think that sometimes the real world just doesn't match with the constraints of whatever library someone is using. I'm not precisely sure what route should be taken but I do think there's a need to make this possible (and it sounds like some projects really make a lot of use of the accumulating errors, so it's hard to say that fail-fast semantics are universally preferred). @sergeykolbasov I'm not seeing the behavior of a mapper only running when all the endpoints succeed, in fact, that is the behavior that led me to start investigating this myself. Is this potentially something that was fixed in a version of Finch? |
To clarify, this does appear to not run the mapper if post("foo" :: withAuth) { user =>
//only runs with auth
} but for example: val withAuth: Endpoint[IO, HNil] = {
if (authed) {
Output.HNil
} else {
Unauthorized(new Exception("Not authorized"))
}
}
val endpoints = withAuth :: (fooEndpoint :+: barEndpoint) the mappers on fooEndpoint or barEndpoint will run for the first of fooEndpoint and barEndpoint that matches, regardless of the output of I'm not sure if this is a super realistic use case, but it appears to subvert the notion that the Mapper only runs when the previous endpoints succeed |
Description
When composing two endpoints with the andThen operator, if the first endpoint does not match, the second one is still evaluated. In particular, a json-body is parsed despite authentication has failed.
Steps to reproduce
Expected Behavior
In both cases, the result should be:
Option[com.twitter.util.Try[String :: Body :: shapeless.HNil]] = Some(Throw(java.lang.Exception: Not Authorized))
Actual Behavior
The results are:
The text was updated successfully, but these errors were encountered: