如何在Play Framework 2.2 / Scala中的ActionBuilder中设置cookie?

时间:2014-03-02 13:30:21

标签: scala cookies playframework playframework-2.2

要设置Cookie,您通常会在Ok().withCookies(…)等操作中操作结果。

我创建了一个AuthenticatedAction extends ActionBuilder[AuthenticatedRequest],并且需要通过有时设置一个新的maxAge的新cookie来更新用户cookie的到期日期。我无法弄清楚如何做到这一点,因为我无法找到一种方法来操纵结果。

invokeBlock函数中,我调用block(new AuthenticatedRequest(identity, request)),它返回Future [SimpleResult],我无法在withCookies()上使用Future[SimpleResult]

这是我的自定义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)
        }
    }
}

1 个答案:

答案 0 :(得分:3)

Ok也是SimpleResult。您无法为Future[SimpleResult]设置Cookie,但您可以这样做:

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

更新 Blankman

使用Cookie回复最简单的情况是这样的:

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

通过这种方式,您可以构建更复杂的Action(例如,来自我的项目):

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]
}