我有一个方法,如果请求中存在用户令牌,则会生成一个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("")
}
但是我开始在项目中使用reactive-mongo,并且对数据库的所有查询都返回Future。我认为真的很好。为了在使用这个reactive-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更相关,但我觉得在通过我的项目编写泛型动作和异步动作时,我会面对这个模式。
提前致谢。
答案 0 :(得分:1)
为此我会使用Play ActionBuilder
,它可以让您将逻辑保存在一个位置,并对Result
和Future[Result]
使用您的操作。
cf:https://playframework.com/documentation/2.4.x/ScalaActionsComposition