Pet*_*ris 5 scala playframework-2.3
我正在为 Play 框架编写一个模块。在我的模块的一部分中,我有以下代码
abstract class SecurityFiltering extends GlobalSettings{
override def onRequestReceived(request: RequestHeader) = {
play.Logger.debug("onRequestReceived: " + request)
super.onRequestReceived(request)
}
override def doFilter(next: RequestHeader => Handler): (RequestHeader => Handler) = {
request => {
play.Logger.debug("doFilter: " + request)
super.doFilter(next)(request)
}
}
override def onRouteRequest(request: RequestHeader): Option[Handler] = {
play.Logger.debug("onRouteRequest: " + request)
super.onRouteRequest(request)
}
}
Run Code Online (Sandbox Code Playgroud)
在 doFilter 方法中,我能够确定以下有用信息
ROUTE_PATTERN = /x/$name<[^/]+>/$age<[^/]+>
ROUTE_CONTROLLER = controllers.Application
ROUTE_ACTION_METHOD = tester
ROUTE_VERB = GET
path = /x/hello
Run Code Online (Sandbox Code Playgroud)
除此之外,我还需要QueryString之前的URL 命名部分的值。因此,在我的测试应用程序中给出以下路线,我需要检索 Name=Pete 和 Age=41
localhost:9000/x/Pete/41
Run Code Online (Sandbox Code Playgroud)
Play 框架中肯定有一些代码已经做到了这一点,但我无法找到它。有人可以建议我如何实现这个目标,或者指出哪个 Play 类提取这些值?
根据JRoper的 GitHub 问题响应
onRequestReceived 负责路由和标记请求,因此,它在第一次调用时不会有任何路由信息,只有在调用后才会有。
val p = """\$([^<]+)<([^>]+)>""".r
override def onRequestReceived(request: RequestHeader) = {
val (taggedRequest, handler) = super.onRequestReceived(request)
val pattern = taggedRequest.tags("ROUTE_PATTERN")
val paramNames = p.findAllMatchIn(pattern).map(m => m.group(1)).toList
val pathRegex = ("^" + p.replaceAllIn(pattern, m => "(" + m.group(2) + ")") + "$").r
val paramValues = pathRegex.findFirstMatchIn(request.path).get.subgroups
val params: Map[String, String] = paramNames.zip(paramValues).toMap
// ^ your params map, will be Map("name" -> "Pete", "age" -> "41")
(taggedRequest, handler)
}
Run Code Online (Sandbox Code Playgroud)
也就是说,通常有更好、更类型安全的方法来实现您想要实现的目标。如果您依赖于 URL 中的特定参数,那么过滤器就不是正确的选择,因为过滤器适用于所有请求,无论它们是否具有这些参数。相反,您可能应该使用操作组合或自定义操作生成器,如下所示:
case class MyAction(name: String, age: Int) extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
// Do your filtering here, you have access to both the name and age above
block(request)
}
}
def foo(name: String, age: Int) = MyAction(name, age) { request =>
Ok("Hello world")
}
def bar(name: String, age: Int) = MyAction(name, age).async { request =>
Future.successful(Ok("Hello world"))
}
Run Code Online (Sandbox Code Playgroud)