我正在构建一个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"))))
}
答案 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} }}