我想知道,如何在PlayFramework 2.x中验证查询字符串参数。 假设我有相当常见的移位,限制(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。 过滤器对此不起作用,导致它们在路由器之后触发。
答案 0 :(得分: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))
}
}
我用它来删除" /"例如,在路线的末端,而不是重定向,这是非常低效的。我也是这样做的,以避免为了匹配结尾" /"而必须写两倍的路线。
答案 1 :(得分:0)
您可以检查控制器Users.list(shift: Int, limit: Int)
中的约束。然后,您可以使用自定义值重定向,而不是抛出异常。防爆。 if (limit > 60) Redirect(routes.controllers.Users.list(shift, 60))
答案 2 :(得分:0)
Michael's方法适用于此,但也有一些有趣的事情。
如果我过滤覆盖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))
}