我从一个动作中调用以下辅助函数来创建一个同步的HTTP-post,其中一个特殊的键值对附加在formdata中的URL参数中:
def synchronousPost(url: String, formdata: Map[String, Seq[String]], timeout: Duration=Duration.create(30, TimeUnit.SECONDS)): String = {
import ExecutionContext.Implicits.global
val params = formdata.map { case (k, v) => "%s=%s".format(k, URLEncoder.encode(v.head, "UTF-8")) }.mkString("&")
val future: Future[WSResponse] = ws.url(url).
withHttpHeaders(("Content-Type", "application/x-www-form-urlencoded")).
post(params)
try {
Await.result(future, timeout)
future.value.get.get.body
} catch {
case ex: Exception =>
Logger.error(ex.toString)
ex.toString
}
}
它被称为:
def act = Action { request =>
request.body.asFormUrlEncoded match {
case Some(formdata) =>
synchronousPost(url, formdata + ("handshake" -> List("ok"))) match {
实际上它是从一些旧的要点复制粘贴的,我很确定它可以用更干净的方式重写。
如何以更干净的方式重写行val params = ...
?这似乎是低水平。
原始的formdata来自request.body.asFormUrlEncoded
,我只需要将handshake参数附加到formdata-map并将原始请求发送回发件人进行握手。
答案 0 :(得分:1)
由于formdata
是Map[String, Seq[String]]
,是一种提供默认WSBodyWritable
的数据类型,您可以直接将其用作请求正文:
val future: Future[WSResponse] = ws.url(url)
.withHttpHeaders(("Content-Type", "application/x-www-form-urlencoded"))
.post(formdata)
顺便提一下,如果使用Await
很容易让Play控制器使用Future[Result]
返回Action.async
,则使用def asyncPost(url: String, formdata: Map[String, Seq[String]]): Future[String] = {
ws.url(url)
.withHttpHeaders(("Content-Type", "application/x-www-form-urlencoded"))
.post(formdata)
.map(_.body)
}
def action = Action.async { request =>
request.body.asFormUrlEncoded match {
case Some(formdata) =>
asyncPost(url, formdata + ("handshake" -> List("ok"))).map { body =>
Ok("Here is the body: " + body)
} recover {
case e =>
Logger.error(e)
InternalServerError(e.getMessage)
}
case None => Future.successful(BadRequest("No form data given"))
}
}
会被视为不良表单,例如:
function remove(obj, key) {
var value = obj[key]
var ret = {}
ret[key] = obj[key]
obj = ret
}