为什么将自定义WrappedRequest与额外的类型参数和ActionFilter组合会导致类型丢失?

时间:2016-01-06 15:49:31

标签: scala playframework playframework-2.4

将将请求转换为自定义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?还是人为错误?

1 个答案:

答案 0 :(得分:1)

使用你的例子,我能够组成这样的动作:

class ExampleController extends Controller {
  def secured = AuthorisedAction().compose(AuthenticationAction()) { request =>
    Ok(request.user.id)
  }
}

有趣的是,在两种情况下,IntelliJ的类型检查都将request视为AuthRequest[AnyContent, TestUser]类型 - 它只是scalac,将其视为WrappedRequest