如何将操作精简程序应用于发送到 SIRD 路由器的所有请求?



假设我有这个 SIRD 路由器:

val adminRouter = Router.from {
case GET(p"/posts") =>
Action { implicit request =>
...
}
}

而这个动作细化器:

object NameSpace {
class SecuredRequest[A](val username: String, request: Request[A]) extends WrappedRequest[A](request)
def securedAction(implicit ec: ExecutionContext) = new ActionRefiner[Request, SecuredRequest] {
def executionContext: ExecutionContext = ec
def refine[A](request: Request[A]): Future[Either[Result, SecuredRequest[A]]] = {
val username = request.session.get("username")
if (username.isDefined)
Future.successful(Right(new SecuredRequest(username.get, request)))
else
Future.successful(Left(Results.Redirect(controllers.routes.AuthController.signInUser())))
}
}
}

然后在我的conf/routes文件中,我有这个

->   /admin   adminRouter

我想做的是在adminRouter到达之前将securedAction操作精简程序应用于发送给的所有请求。因此,adminRouter只会假设所有请求都有一个username字段,如果他们设法到达他。

我是否必须创建一个SecuredAction动作生成器并使用它来创建这样的动作?

case GET(p"/posts") =>
SecuredAction { implicit request =>
...
}

如果你想将SecuredRequest传递给你的处理程序函数,是的,你必须按照你所说的定义一个动作构建器,因为使用的动作构建器决定了提供给动作块的参数的类型。

// note the `R` type parameter
trait ActionBuilder[+R[_], B] extends ActionFunction[Request, R] {
final def apply(block: R[B] => Result): Action[B] = ...
}

您在控制器中获得的默认操作生成器是ActionBuilder[Request, AnyContent]。因此,提供给块的参数被固定为某种请求。

如果您使用这样的操作构建器并调用apply(block: R[B] => Result): Action[B](或任何其他重载的朋友(,您只需获得一个Action[B](基本上是一个带有解析器的EssentialAction(,之后您就没有机会更改块参数类型。

如果此操作可以返回另一个路由器,并且路由器可以对 RequestHead 进行部分模式匹配,则可以实现这一点。

像这样:

val adminRouter = Router.from {
case GET(p"/api/$subPath") =>
SecuredAction { implicit request: SecuredRequest =>
Router.from {
subPath match {
case p"posts" => {
Action { implicit request: SecuredRequest =>
...
}
}
}
}
}
}

但它尚不受支持。

最新更新