【问题标题】:How to refactor PlayFramework Action and Async Action to avoid code duplication?如何重构 PlayFramework Action 和 Async Action 以避免代码重复?
【发布时间】:2015-11-06 21:29:07
【问题描述】:

我有一个方法可以生成验证请求中是否存在用户令牌的操作:

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 时验证用户,我必须编写一个新的 Action 验证方法,如下所示:

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

所以,当我需要在控制器方法中返回 Future 时,我会这样使用它:

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

在尝试重构 HasToken 和 AsyncHasToken 数小时后,我无法产生令人满意的结果。有没有办法更优雅地编写这段代码?

我认为这个问题更多地与重构 scala 函数有关,而不是 Playframework,但我觉得在通过我的项目编写通用 Actions 和 Async Actions 时我会经常遇到这种模式。

提前致谢。

【问题讨论】:

    标签: scala playframework refactoring


    【解决方案1】:

    为此,我将使用 Play ActionBuilder,它可以让您将逻辑保存在一个位置,并同时使用 ResultFuture[Result] 的操作。

    cf:https://playframework.com/documentation/2.4.x/ScalaActionsComposition

    【讨论】:

    • 谢谢,这正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    相关资源
    最近更新 更多