如何将动作优化器应用于发送到 SIRD 路由器的所有请求?

How to apply an action refiner to all requests sent to a SIRD Router?

假设我有这个 SIRD 路由器:

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

而这个 Action Refiner:

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

我想要的是将 securedAction 动作优化器 应用到发送到 adminRouter 的所有请求,然后再发送到它。所以 adminRouter 将假设所有请求都有一个 username 字段,如果他们设法找到他的话。

我是否必须创建一个 SecuredAction action builder 并使用它来创建这样的操作?

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

如果你想将 SecuredRequests 传递给你的处理函数,是的,你必须像你说的那样定义一个 ActionBuilder,因为使用的 ActionBuilder 决定了给操作块的参数类型。

// 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]。所以给block的参数固定为某种Request。

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

如果这个 Action 可以 return 另一个 Router,并且 Routers 可以对 RequestHeader 进行部分模式匹配,那么这是可能的一种方法。

像这样:

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

      Router.from {
        subPath match {
          case p"posts" => {
            Action { implicit request: SecuredRequest =>
              ...
            }
          }
        }
      }
    }
}

但尚不支持。