Play2 - 路线动态部分的验证

时间:2017-05-30 08:11:26

标签: scala validation routes playframework-2.0

我正在构建一个API,它接受一个可变路径参数或路径的动态部分,因为播放文档会指定它。

我想对此进行验证,以便为客户提供正确的回复。

我有以下路线设置

GET /:dynamic/all controller.method(dynamic: String)

该方法的dynamic参数用于API,用于多种方法,因此我希望获得某种可接受字符串的全局验证/白名单。 (例如:"hello"/"hi"将被接受,"noooway"将不被接受,我将返回404 not found作为回复。

我最好希望我的控制器方法不包含任何验证,以便这样做:

def method(dynamic: String): Action[AnyContent] = Action.async { _ =>
    //I already know "dynamic" is valid here.
    Future.successful(Ok(Json.toJson(Map("status" -> "OK"))))
}

而不是:(原谅我的javaisc-psuedo-code)

def method(dynamic: String): Action[AnyContent] = Action.async { _ =>
    val valid = Helper.validate(dynamic)
    if (!valid) return some result/response else 
    Future.successful(Ok(Json.toJson(Map("status" -> "OK"))))
}

1 个答案:

答案 0 :(得分:1)

播放允许您通过不同方式执行此操作。

<强> 1。 PathBindable

您可以为任何类型PathBindable[T]实施T,以便从请求路径中提取的值不是简单String而是T

如果您准备更改dynamic的类型(这是有道理的,因为它不应该只是任何字符串而是有效字符串),您可以执行以下操作:

case class Validated(str: String) {
  assert(Helper.validate(str))
}

object Validated {
  implicit val pathBindable = new PathBindable[Validated] {
    val string = implicitly[PathBindable[String]]
    override def bind(key: String, value: String): Either[String, Validated] = 
      string.bind(key, value).                                           // bind as if it were a string
        right.filter(Helper.validate).getOrElse(Left("Invalid input")).  // filter using your validation function, and give error message
        right.map(Validated(_))                                          // encapsulate in your new type

    override def unbind(key: String, value: Validated): String =
      string.unbind(key, value.str)  //unbind as if it were a string
  }
}

请注意,您需要为反向路由实现unbind(获取给定操作调用的路径)。

现在,您只需要通过String替换路由器和控制器中的your.package.Validated

GET    /:dynamic/all    controller.method(dynamic: your.package.Validated)

NB :如果您想使用班级的简单名称,则需要在build.sbt中导入:

(project in file(".").
  enablePlugins(PlayScala).
  settings(routesImport += "your.package.Validated") 

<强> 2。行动组成

您还可以实现在需要验证输入时使用的操作过滤器:

case class ValidatedAction(input: String) extends ActionFilter[Request] {
  override protected def filter[A](request: Request[A]): Future[Option[Result]] = Future.successful{
    if (Helper.validate(input)) None else Some(BadRequest("Invalid input"))
  }
}

def method(dynamic: String) = (Action andThen ValidatedAction(dynamic)).async {
  Future.successful(Ok)
}

仅当async方法返回filter时,才会执行None块内的代码,否则,它将返回指定的Result(此处为{{1} }}