2015-11-06 75 views
0

我有一个产生一个动作,如果在请求中存在的用户令牌验证的方法:如何重构PlayFramework Action和Async Action以避免代码重复?

def HasToken[A](p: BodyParser[A] = parse.anyContent)(
    f: String => Long => Request[A] => Result): Action[A] = 
    Action(p) { implicit request => 
     request.cookies.get("XSRF-TOKEN").fold { 
     invalidXSRF 
     } { xsrfTokenCookie => 
     val maybeToken = request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey)) 
     maybeToken flatMap { token => 
      cache.get[Long](token) map { userId => 
      if (xsrfTokenCookie.value == token) { 
       f(token)(userId)(request) 
      } else { 
       invalidToken 
      } 
      } 
     } getOrElse noCookie 
     } 
    } 

然后我可以在我的控制器使用这个动作是这样的:

def method = HasToken(parse.empty) { 
token => userId => implicit request => Ok("") 
} 

但我开始使用在项目中的反应-mongo和对数据库的所有查询返回一个Future。我认为真的很好。为了验证用户在使用此功API我不得不写这样的新的行动验证方法:

def AsyncHasToken[A](p: BodyParser[A] = parse.anyContent)(
    f: String => Long => Request[A] => Future[Result])(implicit ec: ExecutionContext): Action[A] = 
    Action.async(p) { implicit request => 
     request.cookies.get("XSRF-TOKEN").fold { 
     Future(invalidXSRF) 
     } { xsrfTokenCookie => 
     val maybeToken = request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey)) 
     maybeToken flatMap { token => 
      cache.get[Long](token) map { userId => 
      if (xsrfTokenCookie.value == token) { 
       f(token)(userId)(request) 
      } else { 
       Future(invalidToken) 
      } 
      } 
     } getOrElse Future(noCookie) 
     } 
    } 

所以,当我需要在我使用它像这样我的控制器方法返回一个未来:

def method() = AsyncHasToken(parse.empty) { 
token => userId => implicit request => Future(Ok("")) 
} 

经过很多小时试图重构HasToken和AsyncHasToken,我还没有能够产生令人满意的结果。有没有办法更优雅地编写这段代码?

我认为这个问题与重构Scala函数比Playframework更相关,但是我觉得在通过我的项目编写通用动作和异步操作时我会面对这种模式。

在此先感谢。

回答