2015-11-06 76 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更相關,但是我覺得在通過我的項目編寫通用動作和異步操作時我會面對這種模式。

在此先感謝。

回答