如何将动作优化器应用于发送到 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 =>
...
}
如果你想将 SecuredRequest
s 传递给你的处理函数,是的,你必须像你说的那样定义一个 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 =>
...
}
}
}
}
}
}
但尚不支持。
假设我有这个 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 =>
...
}
如果你想将 SecuredRequest
s 传递给你的处理函数,是的,你必须像你说的那样定义一个 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 =>
...
}
}
}
}
}
}
但尚不支持。