Run request matching once
waern opened this issue · 1 comments
Hi,
I have a client that does side-effecting request matching. Simplified example:
object AuthRest extends RestHelper {
serve {
case r@Req("api" :: _, _, _) if !isAuthenticated(r) =>
ForbiddenResponse("requiresUserLogin")
}
}
This leads to a race-condition due to how request matching in Lift works. Here is the relevant Lift code:
This Lift logic firsts calls isDefinedAt
(indirectly) to search for a match, triggering a call to isAuthenticated
which can return false, which makes the guard succeed and results in a match. Then once the match has been found, isDefinedAt
is called again (indirectly), here:
This triggers another call to isAuthenticated
. But since isAuthenticated
is an effectful function, it can now return true, causing an exception to be thrown from get
in this line of code:
I think this could be fixed by simply using the lift
method instead of isDefinedAt
from PartialFunction
to match and remember the "continuation" in one go, and then apply the continuation instead of the original partial function to avoid pattern-matching twice.
This is working as intended. Deeper explanation in the mailing list thread, along with suggestions on how to adjust.