鉴于后续ActionBuilder
实施:
class SignedRequest[A](request: Request[A]) extends WrappedRequest[A](request) {}
object SignedAction extends ActionBuilder[SignedRequest] {
def invokeBlock[A](request: Request[A], block: SignedRequest[A] => Future[SimpleResult]) = {
block(new SignedRequest(request))
}
}
class SecuredRequest[A](request: Request[A]) extends WrappedRequest[A](request) {}
object SecuredRequest extends ActionBuilder[SecuredRequest] {
def invokeBlock[A](request: Request[A], block: SecuredRequest[A] => Future[SimpleResult]) = {
block(new SecuredRequest(request))
}
}
我如何组合它们?我尝试了以下......
object MyController extends Controller {
def doSomething = SignedAction.async(parse.json) {
SecuredAction.async(parse.json) { implicit request =>
Future.successful(Ok)
}}
}
...但我总是收到以下错误消息:
/home/j3d/test/controllers/MyController.scala:37: type mismatch;
[error] found : play.api.mvc.Action[play.api.libs.json.JsValue]
[error] required: scala.concurrent.Future[play.api.mvc.SimpleResult]
[error] SecuredAction.async(parse.json) {
^
我错过了什么吗? TX。
答案 0 :(得分:7)
函数async
期待Future[SimpleResult]
,但嵌套的SecuredAction.async
正在将Action
返回到顶部SignedAction.async
(请注意示例代码中的省略声明请求class
和SignedAction
被声明两次。)
您可以将SecuredAction
中的嵌套SignedAction
的结果应用于已签名的请求。
package controllers
import scala.concurrent.Future
import play.api._
import play.api.mvc._
case class SignedRequest[A](request: Request[A])
extends WrappedRequest[A](request) {}
object SignedAction extends ActionBuilder[SignedRequest] {
def invokeBlock[A](request: Request[A],
block: SignedRequest[A] => Future[Result]) =
block(new SignedRequest(request))
}
case class SecuredRequest[A](request: Request[A])
extends WrappedRequest[A](request) {}
object SecuredAction extends ActionBuilder[SecuredRequest] {
def invokeBlock[A](request: Request[A],
block: SecuredRequest[A] => Future[Result]) =
block(new SecuredRequest(request))
}
object MyController extends Controller {
def doSomething = SignedAction.async(parse.json) { signedReq =>
SecuredAction.async(parse.json) { implicit securedReq =>
Future.successful(Ok)
} apply signedReq
}
}
这样的动作组合也可以在没有ActionBuilder
的情况下完成(这会导致一些额外的复杂性)。
package controllers
import scala.concurrent.Future
import play.api._
import play.api.mvc._
case class SignedRequest[A](request: Request[A])
case class SecuredRequest[A](request: Request[A])
object MyController extends Controller {
def Signed[A](bodyParser: BodyParser[A])(signedBlock: SignedRequest[A] => Future[Result]): Action[A] = Action.async(bodyParser) { req =>
signedBlock(SignedRequest(req))
}
def Secured[A](bodyParser: BodyParser[A])(securedBlock: SecuredRequest[A] => Future[Result]): Action[A] = Action.async(bodyParser) { req =>
securedBlock(SecuredRequest(req))
}
def doSomething = Signed(parse.json) { signedReq =>
Secured(parse.json) { implicit securedReq =>
Future.successful(Ok)
} apply signedReq.request
}
}
也可以围绕Future[Result]
:
package controllers
import scala.concurrent.Future
import play.api._
import play.api.mvc._
import play.api.libs.json.JsValue
case class SignedRequest[A](request: Request[A])
case class SecuredRequest[A](request: Request[A])
object MyController extends Controller {
def Signed[A](signedBlock: SignedRequest[A] => Future[Result])(implicit req: Request[A]): Future[Result] = signedBlock(SignedRequest(req))
def Secured[A](signedBlock: SecuredRequest[A] => Future[Result])(implicit req: Request[A]): Future[Result] = signedBlock(SecuredRequest(req))
def doSomething = Action.async(parse.json) { implicit req =>
Signed[JsValue] { signedReq =>
Secured[JsValue] { securedReq => Future.successful(Ok) }
}
}
}
答案 1 :(得分:0)
使用action-zipper,您可以撰写ActionBuilders
import jp.t2v.lab.play2.actzip._
object MyController extends Controller {
val MyAction = SignedAction zip SecuredAction
def doSomething = MyAction.async(parse.json) { case (signedReq, secureReqeq) =>
Future.successful(Ok)
}
}
Json解析只有一次:)
答案 2 :(得分:-2)
简化@applicius答案 我认为可以在没有Future的情况下完成,我认为async / Future是一个单独的问题。
非常简单地删除Futures和async,我们得到了这个:
def signed[A](signedBlock: SignedRequest[A] => Result)(implicit req: Request[A]) = signedBlock(SignedRequest(req))
def secured[A](securedBlock: SecuredRequest[A] => Result)(implicit req: Request[A]) = securedBlock(SecuredRequest(req))
//the use is the same as with Futures except for no async
def doSomething = Action(parse.json) { implicit req =>
signed[JsValue] { signedReq => secured[JsValue] { securedReq =>
Ok
} } }