如何将onRouteRequest全局直接发送到onBadRequest?

时间:2012-11-17 15:59:13

标签: scala playframework global interceptor

我想说我想为所有/ foo URI返回BadRequest结果类型:

override def onBadRequest(r: RequestHeader, error: String) = {
  BadRequest("Bad Request: " + error)
}

override def onRouteRequest(r: RequestHeader): Option[Handler] = {
  if(r.uri.startsWith("/foo") onBadRequest("go away")
  else super.onRouteRequest(r)
}

当然不起作用,因为预期的返回类型是Option[play.api.mvc.Handler]

处理此问题的惯用方法是什么,创建一个默认的应用程序控制器方法来处理过滤的错误请求?理想情况下,因为我在onRouteRequest中知道/ foo实际上是BadRequest,所以我想直接致电onBadRequest

应该注意这是一个人为的例子,实际上是在验证URI yyyyMMdd日期参数,如果它没有解析为JodaTime实例,那么BadRequest-ing - 基本上是一个全能过滤器来清理给定的日期参数而不是处理每个单一的控制器方法调用,更不用说,避免使用无用的堆栈跟踪混乱应用程序日志:无效的日期解析转换(由于用户无意义地操纵,每天都会产生几个MB的垃圾跟踪条目试图获得付费用户内容的uri日期)

1 个答案:

答案 0 :(得分:2)

像往常一样,边缘没有得到答复......

在传递给Play路由器

之前,想出了这个来清理URI日期参数
val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)

override def onRouteRequest(r: RequestHeader): Option[Handler] = {
  import play.api.i18n.Messages
  ymdMatcher.findFirstIn(r.uri) map{ ymd=>
    try { ymd2Date( ymd); super.onRouteRequest(r) }
    catch { case e:Exception => // kick to "bad" action handler on invalid date 
      Some(controllers.Application.bad(Messages("bad.date.format"))) 
    }
  } getOrElse(super.onRouteRequest(r))
}