1

我想知道,如何在 PlayFramework 2.x 中验证查询字符串参数。假设我有非常常见的 shift、limit (DROP, LIMIT) 参数用于序列,并且我有这样的路线:

# http://example.com/users?shift=0&limit=20 - take first 20 users
GET    /users         Users.list(shift: Int ?= 0, limit: Int ?= 20)

我想将我的班次和限制保持在正确的范围内,例如从 1 到 60 的限制,如果用户尝试设置像 23979 这样的限制,它应该减少到 60。过滤器对此不起作用,因为它们在路由器之后触发。

4

3 回答 3

1

我确实喜欢 biesor 的评论,您可以在行动开始时进行验证。如果那不可能,kfer38 的答案也可以。我想抛出另一个答案,那就是使用 Global 对象。http://www.playframework.com/documentation/2.3.x/ScalaGlobal

全局对象优于重定向的优点是它可以立即完成并重新配置路由器,而不是重定向会增加运行时间的毫秒数。由于在路由器接触它们之前做事似乎是一个问题,我提供了这个解决方案。

像这样的东西会起作用:

object Global extends GlobalSettings {
  override def onRouteRequest(request: RequestHeader): Option[Handler] = {
    // string matching here to get the values
    // rewrite values to what you want
    super.onRouteRequest(request.copy(path = newPath))
  }
}

例如,我使用它来删除路由末尾的“/”,而不是重定向,这确实是低效的。我也这样做是为了避免为了匹配结尾“/”而编写两倍的路由。

于 2014-07-01T19:30:56.893 回答
0

您可以检查控制器中的约束Users.list(shift: Int, limit: Int)。然后,您可以使用自定义值重定向,而不是引发异常。前任。if (limit > 60) Redirect(routes.controllers.Users.list(shift, 60))

于 2014-07-01T13:25:14.923 回答
0

Michael 的方法对此很有效,但也有一些有趣的事情。如果我过滤查询参数覆盖onRouteRequest它过滤传递给动作函数的参数,但不过滤请求对象中的查询字符串参数:

def users(shift: Int, limit: Int) = Action { req =>
  Logger.debug("shift: " + shift)
  Logger.debug("shiftQS: " + req.getQueryString("shift"))

如果我们要求/users?shift=-2我们的班次将被过滤,而 shiftQS 不会!但是如果你只使用,情况似乎有所不同Filter,它可以过滤查询字符串参数,但不能过滤你的参数。因此,要过滤查询字符串,您应该添加 Play 的Filter. 我的最终实现包含如下内容:

// Write your filter and mix it to Global
object SeqFilter extends EssentialFilter {
  def apply(next: EssentialAction): EssentialAction = new EssentialAction {
    def apply(req: RequestHeader): Iteratee[Array[Byte], SimpleResult] = {
      next(doFilter(req))
    }
  }

  def doFilter(req: RequestHeader): RequestHeader = {
    if (/* queryString contains invalid parameters */) {
      val qs = /* You filtered queryString */
      req.copy(queryString = qs)
    } else {
      req
    }
  }
}

// Alson use your filter in onRouteRequest in Global object
override def onRouteRequest(req: RequestHeader): Option[Handler] = {
  super.onRouteRequest(SeqFilter.doFilter(req))
}
于 2014-07-02T08:40:13.237 回答