Виконання HTTP-запиту в Scala


74

Я намагаюся надіслати простий запит POST веб-службі, яка повертає трохи XML у Scala.

Здається, Dispatch - це стандартна бібліотека, яка використовується для цього завдання, але я не можу знайти документацію до нього. Основний сайт, на який я посилаюся вище, детально пояснює, що таке обіцянка і як виконувати асинхронне програмування, але насправді не документує API. Існує таблиця Менделєєва - яка виглядає дещо страшною, - але вона здається корисною лише людям, які вже знають, що робити, і їм потрібне лише нагадування для загадкового синтаксису.

Також здається, що Scalaz має певний пристрій для HTTP , але я також не можу знайти жодної документації для нього.



1
Дякуємо за API. З цього я можу зрозуміти, як насправді користуватися бібліотекою. Тим не менше, я хотів би мати щось середнє, наприклад, високий рівень опису API. Я уявляю щось на зразок "Щоб зробити запит POST, ви використовуєте цей конструктор з цими параметрами тощо".
Андреа

Погодились, що Dispatch може використовувати кращу документацію. На мою думку, зараз найкраще поставити запитання в групі Google: groups.google.com/forum/#!forum/dispatch-scala
pr1001

Відповіді:


132

Я використовую наступне: https://github.com/scalaj/scalaj-http .

Ось простий запит GET:

import scalaj.http.{Http, HttpOptions}

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

і приклад 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 доступний через SBT:

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

Я виявляється найпростішим варіантом! Мені все ще цікаво дізнатись про Dispatch та причину його своєрідного синтаксису
Андреа

9
Примітка: за замовчуванням час очікування підключення досить низький (100 міліс), тому, якщо ви отримуєте java.net.SocketTimeoutException: connect timed out, додайте рядок, наприклад.option(HttpOptions.connTimeout(10000))
theon

1
Він більше не сумісний із scala 2.11, оскільки вони видалили ScalaObject. Нетерпляче чекаючи, поки scalaj-http оновить свою бібліотеку.
Nativ

2
@Dalvik Я думаю, що вони очистили свою гру; просто додайте "org.scalaj" %% "scalaj-http" % "1.1.4"до build.sbt.
Феліпе

Я не впевнений, що хтось ще мав проблеми з отриманням відповіді із запитом "asParamsMap", але в підсумку мені довелося використовувати "asString", а потім явно проаналізувати net.minidev.json.parser.JSONParser.
th3morg

7

Ви можете використовувати спрей-клієнт . Документації бракує (мені знадобилося трохи копати, щоб дізнатись, як робити запити GET із параметрами запиту ), але це чудовий варіант, якщо ви вже використовуєте спрей. І документація краща за відправлення.

Ми використовуємо його на AI2 над відправленням, оскільки оператори менш символічні, і ми вже використовуємо спрей / актори.

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)

Основний розробник спрею перейшов на akka, тому навіть той спрей, який готовий до виробництва, буде застарілим, а AKKA-HTTP та AKKA-STREAMS стануть наступним туром для http-клієнтів та серверів. akka.io/docs
Генрі Х.

5

Я використовую відправлення: http://dispatch.databinder.net/Dispatch.html

Вони щойно випустили нову версію (0.9.0) із абсолютно новим API, який мені дуже подобається. І це асинхронізація.

Приклад зі сторінки проекту:

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

for (c <- country)
  println(c)

редагувати: Це може допомогти вам https://github.com/dispatch/reboot/blob/master/core/src/main/scala/requests.scala


Так, я зв’язав сторінку проекту. Але я не можу знайти там, як зробити простий запит POST - або навіть запит GET з параметрами та / або спеціальними заголовками.
Андреа

@Andrea - спробуйте це посилання: flotsam.nl/dispatch-periodic-table.html . Здається, dispatchна даний момент у автора є деякі проблеми з основним документом - буквально вчора документи були набагато кращими.
Рогач

@Rogach це не лише для старої відправки? Андреа: оновила мій пост посиланням на джерела
drexin

зараз може:val svc = url("http://diasporafoundation.org/").POST.setBody("test")
ВасильНовіков


3

Використання моєї бібліотеки Requests-Scala :

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

Це так просто, як

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

Чудово Лі, у мене також є певні сумніви, як щодо того, якщо я хочу передати Json даним у запитах. Post, чи потрібно мені витягувати кожну пару значень ключа. Чи не існує простого підходу.
Мохаммад Ріджван,

Зрозумів, val json = "" "{" key ":" value "}" "". StripMargin val r = request.post (url, data = json) val json = ujson.read (r.text ()) println (json)
Мохаммад Ріджван,

2

Якщо я можу зробити безсоромний штекер, у мене є API під назвою Bee-Client, який є просто обгорткою в Scala для Java HttpUrlConnection.


Дякую. Чи є якась документація?
Андреа

Так, але це все ще обмежено. Я працюю над деякими прикладами звичаїв. На даний момент подивіться на тестовий код, особливо на тест інтеграції bitbucket.org/rickb777/lighthttpclient/src/a6c526e4684b/src/…
Rick-777

Зараз є деяка документація на wiki bitbucket.org/rickb777/lighthttpclient/wiki/Home
Rick-777

Добре! Але це, здається, приватно. Зараз у мене немає своїх облікових даних Bitbucket. Можливо, ви забули позначити вікі як загальнодоступну
Андреа

Вибачте за це. Я замість цього перемістив документи на свій веб-сервер: bigbeeconsultants.co.uk/light-http-client Я також розширив документацію.
Рік-777,


1

Мені довелося зробити те ж саме, щоб перевірити одну кінцеву точку (в тесті інтеграції). Отже, нижче наводиться код для отримання відповіді із запиту GET у Scala. Я використовую scala.io.Source для читання з кінцевої точки та ObjectMapper для перетворення json в об'єкт.

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)

І ось мій метод тестування на те саме

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

0

Ось клас, над яким я працював. Він має як запити GET, так і POST. ОТРИМАТИ без параметрів - POST із параметрами Я використовував його для спілкування з StreamSets, щоб запустити конвеєр або перевірити стан конвеєра.

йому потрібна лише наступна залежність у файлі build.sbt:

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

Ви можете знайти документацію тут: 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"
    }
  }

}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.