Ama*_*man 6 scala playframework-2.0
我通过覆盖GlobalSettings的onRouteRequest方法来拦截对我的播放应用程序的所有请求.现在,我需要从这里向调度的动作发送一些数据,这样我就不会在所有动作中执行所有这些计算.如何设置我传递给超级onRouteRequest方法的请求(play.api.mvc.RequestHeader)对象的属性?
为了满足您的需要,我不认为使用onRouteRequestwill 有效(至少优雅地)。
但是我们尝试使用专用的结构来拦截。
以下是如何拦截请求、计算一些通用内容并将其传递给 Action
首先,这是一个Interceptor具有方法intercept和便捷方法的对象username:
object Interceptor {
def intercept[A, B](f: RequestHeader => Option[B], e: RequestHeader => Result)(action: B => Action[A]): Action[(Action[A], A)] = {
val bodyParser = BodyParser {
request =>
f(request) map {
b =>
val innerAction = action(b)
innerAction.parser(request).mapDone {
body => body.right.map(innerBody => (innerAction, innerBody))
}
} getOrElse {
Done(Left(e(request)), Input.Empty)
}
}
Action(bodyParser) {
request =>
val (innerAction, innerBody) = request.body
innerAction(request.map(_ => innerBody))
}
}
def username[A](check: RequestHeader => Option[String]): ((String) => Action[A]) => Action[(Action[A], A)] = intercept(check, r => Results.Unauthorized("not logged in"))
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,工作函数intercept使您有机会根据请求内容计算一些内容。哪种类型的计算结果B可能会失败 ( Option),在这种情况下,处理程序会告诉我们要做什么。
定义要计算的内容后,您可以使用接受 a并给出 的action函数来定义您的计算。BAction[A]
该username方法只是一个简单的预定义拦截器,可以让我们定义如何检索登录的用户名,仅用于说明。
现在我们将如何在您的应用程序中使用它们Controller
//index is defined for both GET and POST in routes, but fails on POST
// thanks to the interceptor that checks at first the used method
// the case mustn't be handled in the Action definition
def index = Interceptor.intercept(
/*check the method*/
request => if (request.method == "GET") Some(request.method) else None,
/*not a GET => bad request*/
request => BadRequest(request.method + " not allowed")
) { /*the computation result*/method => Action {
Ok("The method : " + method)
}
}
//this controller retrieve the username in the session and renders it in a OK response
def secured = Interceptor.username(r => r.session.get("username")) { username => Action {
Ok("You're logged in as " + username)
}
}
//this enables you to logged in => store in session
def login(u:String) = Action { request => {
Ok("Logged in as " + u) withSession(("username" -> u))
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您有通用计算,您可以创建预配置的拦截器(这里我使用案例类,但只需定义一个部分应用的函数就interceptor足够了)
case class Intercept[B] (f: RequestHeader => Option[B], e: RequestHeader => Result) {
def apply[A](action: B => Action[A]) = Interceptor.intercept[A,B](f, e)(action)
}
val getInterceptor = Intercept[String](
request => if (request.method == "GET") Some(request.method) else None,
request => BadRequest(request.method + " not allowed")
)
def index2 = getInterceptor { method => Action {
Ok("Da method : " + method)
}
}
Run Code Online (Sandbox Code Playgroud)
与评论相关的编辑:
根据您的评论,这是您可以如何使用拦截器(请注意,我已经模拟了主机检索和检查)
使用hosted和anotherHosted,您将能够测试此工作流程:
这是代码
def getHost(request:RequestHeader) = request.queryString.get("host").get.head
def checkHost(host:String, b: Boolean) = b
val checkHosted = (b: Boolean) => Intercept[String](
request => {
val host = getHost(request)
Cache.getAs[String](host) match {
case x@Some(_) => x
case None => if (checkHost(host, b)) {
Cache.set(host, host)
Some(host)
} else None
}
},
request => NotFound(getHost(request) + "not hosted")
)
def hosted(b:String) = checkHosted(b.toBoolean) {
host => Action {
Ok("this host is ok : " + host)
}
}
def anotherHosted(b:String) = checkHosted(b.toBoolean) {
host => Action {
Ok("this host is ok : " + host)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1468 次 |
| 最近记录: |