2017-10-02 2 views
0

J'appelle la fonction d'assistance suite d'une action pour faire une syncronous HTTP post avec une paire spéciale clé-valeur ajoutée à l'URL-paramètres formdata:Adjonction à formdata donné pour le post http

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 
    } 
    } 

il est appelé comme ceci:

def act = Action { request => 
    request.body.asFormUrlEncoded match { 
     case Some(formdata) => 
     synchronousPost(url, formdata + ("handshake" -> List("ok"))) match { 

en fait, il est collé copie de certains vieux gIST et je suis tout à fait sûr qu'il peut être réécrite d'une manière plus propre.

Comment réécrire la ligne val params = ... de manière plus propre? Il semble être bas niveau.

Le formulaire d'origine provient de request.body.asFormUrlEncoded et j'ai simplement besoin d'ajouter le paramètre handshake à formdata-map et de renvoyer la demande initiale à l'expéditeur pour qu'il effectue la négociation.

+1

Pouvez-vous pas seulement 'post (formdata)' directement sans convertir en une chaîne? Il y a un 'WSBodyWritable' pour les données de Map [String, Seq [String]]' [fournies] (https://github.com/playframework/play-ws/blob/b95e3483fed79c063accbe88e8734d9b6db9d33a/play-ws-standalone/src/main /scala/play/api/libs/ws/DefaultBodyWritables.scala#L107) – Mikesname

+0

@Mikes: si facile! Comme je l'ai dit, l'essentiel était assez vieux ... Voulez-vous ajouter une vraie réponse? Sinon, je révoquerais la question ... – Bastl

Répondre

1

Depuis formdata est un Map[String, Seq[String]], un type de données pour lequel un défaut WSBodyWritable est fourni, vous pouvez simplement l'utiliser comme corps de demande directement:

val future: Future[WSResponse] = ws.url(url) 
    .withHttpHeaders(("Content-Type", "application/x-www-form-urlencoded")) 
    .post(formdata) 

Soit dit en passant, il est considéré comme une mauvaise forme à utiliser Await quand il est facile de faire des contrôleurs de jeu renvoient un Future[Result] en utilisant Action.async, par exemple:

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")) 
    } 
}