web-dev-qa-db-fra.com

Faire une requête HTTP dans Scala

J'essaie d'émettre une simple requête POST à un service Web qui renvoie du code XML dans Scala.

Il semble que Dispatch soit la bibliothèque standard utilisée pour cette tâche, mais je ne trouve pas de documentation à ce sujet. Le site principal, que je renvoie ci-dessus, explique en détail ce qui constitue une promesse et comment faire de la programmation asynchrone, mais ne documente pas réellement l'API. Il existe un tableau périodique - qui a l'air un peu effrayant - mais il ne semble utile que pour les personnes qui savent déjà quoi faire et qui n'ont besoin que d'un rappel pour la syntaxe cryptique.

Il semble également que Scalaz a quelques fonctionnalités pour HTTP , mais je ne trouve pas non plus de documentation à ce sujet.

69
Andrea

J'utilise ce qui suit: https://github.com/scalaj/scalaj-http .

Voici une simple requête GET:

import scalaj.http.Http

Http("http://foo.com/search").param("q", "monkeys").asString

et un exemple de POST:

val result = Http("http://example.com/url").postData("""{"id":"12","json":"data"}""")
  .header("Content-Type", "application/json")
  .header("Charset", "UTF-8")
  .option(HttpOptions.readTimeout(10000)).asString

Scalaj HTTP est disponible via SBT:

libraryDependencies += "org.scalaj" % "scalaj-http_2.11" % "2.3.0"
116
kulikov

Vous pouvez utiliser spray-client . La documentation fait défaut (il m'a fallu des recherches approfondies pour savoir comment faire des requêtes GET avec des paramètres de requête ), mais c'est une excellente option si vous utilisez déjà le spray. Et la documentation est meilleure que l'envoi.

Nous l'utilisons à AI2 plus dispatch parce que les opérateurs sont moins symboliques et que nous utilisons déjà un spray/des acteurs.

import spray.client.pipelining._

val url = "http://youruri.com/yo"
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive

// Post with header and parameters
val responseFuture1: Future[String] = pipeline(Post(Uri(url) withParams ("param" -> paramValue), yourPostData) map (_.entity.asString)

// Post with header
val responseFuture2: Future[String] = pipeline(Post(url, yourPostData)) map (_.entity.asString)
6
schmmd

J'utilise dispatch: http://dispatch.databinder.net/Dispatch.html

Ils viennent de publier une nouvelle version (0.9.0) avec une nouvelle API complète que j'aime beaucoup. Et c'est asynchrone.

Exemple de page de projet:

import dispatch._
val svc = url("http://api.hostip.info/country.php")
val country = Http(svc OK as.String)

for (c <- country)
  println(c)

edit: Cela pourrait vous aider https://github.com/dispatch/reboot/blob/master/core/src/main/scala/requests.scala

5
drexin

Une autre option est le play-ws de Typesafe, qui est la bibliothèque Play Framework WS divisée en une bibliothèque autonome:

http://blog.devalias.net/post/89810672067/play-framework-seperated-ws-library

Je ne proposerais pas nécessairement cela comme la meilleure option, mais il convient de le mentionner.

3
tksfz

Pourquoi ne pas utiliser Apache HttpComponents ? Voici le FAQ de l'application , qui couvre un large éventail de scénarios.

2
Brian Agnew

Si je peux faire un plug sans vergogne, j'ai une API appelée Bee-Client qui est simplement un wrapper dans Scala pour HttpUrlConnection de Java.

2
Rick-777

Je devais faire la même chose pour tester un point final (dans le test d'intégration). Voici donc le code pour extraire la réponse de la requête GET dans Scala. Je me sers de scala.io.Source pour lire à partir du noeud final et ObjectMapper pour la conversion json en objet.

private def buildStockMasterUrl(url:String, stockStatus:Option[String]) = {
      stockStatus match  {
        case Some(stockStatus) => s"$url?stockStatus=${stockStatus}"
        case _ => url
    }
  }

    private def fetchBooksMasterData(stockStatus:Option[String]):  util.ArrayList[BooksMasterData] = {
    val url: String = buildBooksMasterUrl("http://localhost:8090/books/rest/catalogue/booksMasterData",stockStatus)
    val booksMasterJson : String = scala.io.Source.fromURL(url).mkString
    val mapper = new ObjectMapper()
    apper.readValue(booksMasterJson,classOf[util.ArrayList[BooksMasterData]])
}

case class BooksMasterData(id:String,description: String,category: String)

Et voici ma méthode de test pour le même

test("validate booksMasterData resource") {
    val booksMasterData = fetchBooksMasterData(Option(null))
    booksMasterData.size should be (740)
  }
1
Sanjay Bharwani

Utilisation de ma bibliothèque Requests-Scala :

// Mill
ivy"com.lihaoyi::requests:0.1.8"
// SBT
"com.lihaoyi" %% "requests" % "0.1.8"

C'est aussi simple que

val r = requests.get("https://api.github.com/users/lihaoyi")

r.statusCode
// 200

r.headers("content-type")
// Buffer("application/json; charset=utf-8")

r.text
// {"login":"lihaoyi","id":934140,"node_id":"MDQ6VXNlcjkzNDE0MA==",...
val r = requests.post("http://httpbin.org/post", data = Map("key" -> "value"))

val r = requests.put("http://httpbin.org/put", data = Map("key" -> "value"))

val r = requests.delete("http://httpbin.org/delete")

val r = requests.head("http://httpbin.org/head")

val r = requests.options("http://httpbin.org/get")
1
Li Haoyi

Voici un cours sur lequel je travaillais. Il a à la fois les requêtes GET et POST. GET sans paramètres - POST avec les paramètres que j'ai utilisés pour communiquer avec StreamSets afin de démarrer un pipeline ou de vérifier un pipeline statut.

il n'a besoin que de la dépendance suivante dans le fichier build.sbt:

libraryDependencies += "org.scalaj" %% "scalaj-http" % "2.3.0"

Vous pouvez trouver la documentation ici: https://github.com/scalaj/scalaj-http#post-raw-arraybyte-or-string-data-and-get-response-code


import scala.collection.mutable.ArrayBuffer
import scalaj.http.{Http, HttpResponse}

object HttpRequestHandler {

  val userName: String = "admin"
  val password: String = "admin"

  def sendHttpGetRequest(request: String): String = {

    println(" Send Http Get Request (Start) ")

    try {

      val httpResponse: HttpResponse[String] = Http(request).auth(userName,password)
                                                            .asString

      val response = if (httpResponse.code == 200) httpResponse.body
      else{
        println("Bad HTTP response: code = "+httpResponse.code )
        return "ERROR"
      }

      println(" Send Http Get Request (End) ")

      return response

    } catch {
      case e: Exception => println("Error in sending Get request: "+e.getMessage)
        return "ERROR"
    }


  }

  def arrayBufferToJson(params:ArrayBuffer[(String,String)]): String ={

    var jsonString = "{"
    var count: Int = 0
    for(param <- params){
      jsonString+="\""+param._1+"\":\""+param._2+"\""+ ( if(count!=params.length-1) "," else "")
      count+=1
    }
    jsonString+="}"

    return jsonString

  }

  def sendHttpPostRequest(request: String,params: ArrayBuffer[(String,String)]): String = {

    println(" Send Http Post Request (Start) ")

    try {
      val postData : String = arrayBufferToJson(params)
      println("Parameters: "+postData)
      val httpResponse: HttpResponse[String] = Http(request).auth(userName,password)
                                                            .header("X-Requested-By","sdc")
                                                            .header("Content-Type", "application/json;charset=UTF-8")
                                                            .header("X-Stream" , "true")
                                                            .header("Accept", "application/json")
                                                            .postData(postData.getBytes)
                                                            .asString


      val response = if (httpResponse.code == 200) httpResponse.body
      else{
        println("Bad HTTP response: code = "+httpResponse.code )
        "ERROR"
      }

      println(" Send Http Post Request (End) ")

      return response

    } catch {
      case e: Exception => println("Error in sending Post request: " + e.getMessage)
        return "ERROR"
    }
  }

}

0
Abdelrahman Aly