我需要检查每个请求是否存在YMD uri日期参数,如果存在,则将其存储在Request中,以便稍后访问应用程序的各个部分,其中隐式请求已可用。
请求拦截似乎是一个明显的选择: https://github.com/playframework/Play20/wiki/ScalaInterceptors
但是,我没有看到添加到请求的方法(实际上RequestHeader
是可用的),假设它是只读/不可变的。
我可以通过Action Composition向请求添加数据;然而,这种方法仅限于组合动作,而不是每个动作(为什么我喜欢上面的全局Before Interceptor方法以某种方式工作)。例如,Authentiucated动作包装器允许我将登录用户的id存储在请求中。
trait Secured {
private case class Success[A](uid: Int, r: Request[A]) extends WrappedRequest(r)
def Authenticated[A](p: BodyParser[A])
(f: Success[A] => Result)(implicit group: RoleGroup) = {
def apply(maybeUser: Option[String])(implicit r: Request[A]) = {
maybeUser map {id =>
Cache.orElse(group.to_s+"-"+id, 3600){
repo.user.get(id.int, group) map(_.active) getOrElse false
} fold ( onFail, f(Success(id.int, r)) )
}
}
我想对可能的uri日期参数做同样的事情,但是它适用于所有的动作,或者在通过全局拦截器触发Play路径机制之前再次应用它。
非常感谢,非常感谢
答案 0 :(得分:0)
要模拟将任意数据注入Request,您可以扩展WrappedRequest:
case class Outcome[A](
r: Request[A],
uid: Int,
startDate: String,
endDate: String,
uriDate: JodaTime) extends WrappedRequest(r)
然后创建Action提供程序特征,返回自定义请求包装器的实例。例如,基本任务操作可能如下所示:
trait TaskRequest
extends DateParser {
def Task[A](p: BodyParser[A])(f: Outcome[A] => Result) = {
Action(p) { implicit r =>
f( toOutcome[A](r, r.session.get("userID").map(_.toInt) getOrElse 0) )
}
}
def Task(f: Outcome[AnyContent] => Result): Action[AnyContent] = {
import play.api.mvc.BodyParsers._
Task(parse.anyContent)(f)
}
protected def toOutcome[A](r: Request[A], uid: Int) = {
val(start,uriDate) = (startDate(r), toDate(r.uri))
val end = seasonEnd(start)
Outcome(r, uid, start.toString("yyyyMMdd"), end.toString("yyyyMMdd"), uriDate)
}
val ymdMatcher = "\\d{8}".r
protected def startDate(uri: String) = {
ymdMatcher.findFirstIn(uri). // set season start based on ymd URI param if exist
map(_.startDate) getOrElse seasonStart(new JodaTime)
}
protected def toDate(uri: String) =
ymdMatcher.findFirstIn(r.uri).map(_.to_date) getOrElse new JodaTime
}
然后从任务中获取经过身份验证的操作:
trait Secured
extends TaskRequest {
def Authenticated[A](p: BodyParser[A])
(f: Outcome[A] => Result)(implicit group: RoleGroup) = {
def apply(maybeUser: Option[String])(implicit r: Request[A]) = {
maybeUser map {id =>
Cache.orElse(group.to_s+"-"+id, 3600){
repo.user.get(id.int, group) map(_.active) getOrElse false
} fold ( onFail, f( toOutcome(r, id.int)) )
}
}
然后在您的控制器中使用:
def index = Authenticated { implicit request=>
// voila, current season start date since no uri date param exist
request.startDate
}
我可以基于每个操作调用日期操作函数,但是只适用于Action范围。我如何访问模板层中的startDate?我不能,但使用自定义请求包装器,您可以注入任何您想要的东西,并轻松在任何地方引用数据。因此,而不是将游戏的请求纳入范围:
@(model: Foo, title: String)(implicit request: play.api.mvc.Request[_])
您引用自定义请求包装器:
@(model: Foo, title: String)(implicit request: controllers.Outcome[_])
这项工作是否相当不错,全局拦截我还没有找到用途(可能重新路由一些遗留URI,但没有像WrappedRequest方法那样强大)