2014-03-02 86 views
1

要設置Cookie,您通常會在Ok().withCookies(…)等操作中操作結果。如何在Play Framework 2.2/Scala中的ActionBuilder中設置cookie?

我創建了一個AuthenticatedAction extends ActionBuilder[AuthenticatedRequest],並且需要通過使用新的maxAge有時設置新的cookie來更新用戶cookie的到期日期。我無法弄清楚如何做到這一點,因爲我找不到操作結果的方法。

invokeBlock函數內,我調用block(new AuthenticatedRequest(identity, request)),它返回Future [SimpleResult],我不能在Future[SimpleResult]上使用withCookies()

這裏是我的自定義AuthenticatedAction:

class AuthenticatedRequest[A](val identity: Identity, request: Request[A]) extends WrappedRequest[A](request) 

object AuthenticatedAction extends ActionBuilder[AuthenticatedRequest] { 
    def redirectToLogin = { 
     Redirect("/login") 
    } 

    def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[SimpleResult]) = { 
     request.cookies.get("mycookie").map { cookie => 

      val maybeIdentity = Auth.validateAndTouchTokenAndGetUser(cookie.value) 
      maybeIdentity.map { identity => 

       // If it's a persistent session, update timestamp by sending a new cookie sometimes! 
       // To simplify this example, assume we always want to set a new cookie. 
       val futureResult = block(new MaybeAuthenticatedRequest(maybeIdentity, request)) 
       // What next? 
       val newMaxAge = 1234 
       // ???result???.withCookies(Cookie("mycookie", cookie.value, newMaxAge)) 

      } getOrElse { 
       // Respond with redirect to login and delete cookie and a warning message 
       Future.successful(
        redirectToLogin 
        .discardingCookies(DiscardingCookie("mycookie")) 
        .flashing("warning" -> "Your session has expired. Please sign in again.") 
       ) 
      } 

     } getOrElse { 
      // Respond with redirect to login 
      Future.successful(redirectToLogin) 
     } 
    } 
} 

回答

3

OkSimpleResult爲好。你不能設置Cookie的Future[SimpleResult],但你可以這樣做:

val futureResult: Future[SimpleResult] = ... 
futureResult.map(_.withCookies(Cookie("mycookie", cookie.value, newMaxAge)) 

更新Blankman

與餅乾響應的simpliest的情況是這樣的:

def myAction = Action { 
    ..... 
    Ok(response).withCookies(Cookie("cookie", cookieValue, maxAge)) 
} 

這你可以用這種方式組合更復雜的動作(例如我的項目):

def safe(doSafe: Request[AnyContent] => Future[SimpleResult]): Action[AnyContent] = Action.async { implicit request => 
    try { 
    doSafe(request).map(_.withCookies(Cookie("mycookie", cookie.value, newMaxAge)) 
    } catch { 
    case e: Exception => 
     e.printStackTrace() 
     //custom failure response here 
    } 
} 

用法:

def someAction = safe { implicit request => 
    .... //something that returns a Future[SimpleResult] 
} 
+0

完美,這作品! – Nick

+0

@seriejja我有一個類似的問題,但我不是100%確定你的代碼片段應該去哪裏?我需要從自定義Action內部創建一個cookie,但不確定。你介意澄清在哪裏做到這一點? – Blankman

+1

@Blankman請看我的編輯 – serejja

相關問題