将将请求转换为自定义ActionBuilder
的{{1}}与其他类型参数相结合,然后将其与WrappedRequest
相结合,会导致自定义ActionFilter
的类型被放弃。
为什么会这样,是否有修复?
例如,假设我需要身份验证WrappedRequest
和可选的授权ActionBuilder
,其中我们需要的用户类型可能因使用情况而异。
看到这个人为的代码:
ActionFilter
请注意:由于case class AuthRequest[A, U](val request: Request[A], val user: U) extends WrappedRequest[A](request)
case class TestUser(id: String)
case class AuthenticationAction[A]() extends ActionBuilder[({type λ[B] = AuthRequest[B, TestUser]})#λ] {
override def invokeBlock[A](request: Request[A], block: (AuthRequest[A, TestUser]) => Future[Result]): Future[Result] =
block(AuthRequest(request, TestUser("test-id")))
}
case class AuthorisedAction[A]() extends ActionFilter[({type λ[B] = AuthRequest[B, TestUser]})#λ] {
// does some additional authorisation checks for added security
def authorised(user: TestUser) = true
override def filter[A](request: AuthRequest[A, TestUser]) = Future.successful {
if( authorised(request.user) ) None
else Some(Unauthorized)
}
}
上的其他类型参数,因此this answer需要上述类型函数。同样这是必需的,因为此API将与多种类型的用户一起使用。
如果我然后实现使用上述的控制器:
AuthRequest
我收到编译错误(class ExampleController extends Controller {
def secured = (AuthenticationAction() andThen AuthorisedAction()) { request =>
Ok(request.user.id)
}
}
)。换句话说,上面的变量value user is not a member of play.api.mvc.WrappedRequest[play.api.mvc.AnyContent]
的类型是request
而不是预期的WrappedRequest
类型!
我了解大多数用例AuthRequest[play.api.mvc.AnyContent, TestUser]
和AuthenticationAction
会合并为一个操作,但由于授权是可选的,我希望将这些用作单独的问题。
这可能吗?这是Play Framework API中的错误吗?还是一个Scala bug?还是人为错误?
答案 0 :(得分:1)
使用你的例子,我能够组成这样的动作:
class ExampleController extends Controller {
def secured = AuthorisedAction().compose(AuthenticationAction()) { request =>
Ok(request.user.id)
}
}
有趣的是,在两种情况下,IntelliJ的类型检查都将request
视为AuthRequest[AnyContent, TestUser]
类型 - 它只是scalac,将其视为WrappedRequest
。