在Scala中执行HTTP请求


74

我正在尝试向Web服务发出简单的POST请求,该请求会在Scala中返回一些XML。

看来Dispatch是用于此任务的标准库,但我找不到有关它的文档。我上面链接的主站点详细解释了什么是诺言以及如何进行异步编程,但实际上并未记录API。有一个周期表-看起来有点吓人-但它仅对已经知道要做什么并且只需要提醒隐式语法的人有用。

Scalaz似乎也有一些用于HTTP的功能,但我也找不到任何文档。



1
谢谢您的API。由此,我也许能够弄清楚如何实际使用该库。尽管如此,我还是希望有一些中间内容,例如对API的高级描述。我想像着“要发出POST请求,请使用带有这些参数的构造函数,以此类推”。
安德里亚(Andrea)2012年

同意Dispatch可以使用更好的文档。我认为目前最好的选择是在Google
网上论坛上发问

Answers:


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

可通过SBT使用Scalaj HTTP:

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

事实证明,这是最简单的选择!我仍然很想了解Dispatch及其特殊语法的原因
Andrea 2012年

9
注:默认的连接超时是相当低(100个米利斯),所以如果你接收java.net.SocketTimeoutException: connect timed out,然后添加一行如.option(HttpOptions.connTimeout(10000))
席恩

1
它已与Scala 2.11不再兼容,因为他们删除了ScalaObject。急切地等待scalaj-http更新其库。
Nativ 2014年

2
@Dalvik我认为他们已经清理了比赛;只需添加"org.scalaj" %% "scalaj-http" % "1.1.4"到build.sbt。
费利佩

我不确定其他人是否在发布时收到“ asParamsMap”的响应时遇到麻烦,但是我最终不得不使用“ asString”,然后使用net.minidev.json.parser.JSONParser进行了明确的解析。
th3morg

7

您可以使用spray-client。缺少文档(花了我一些时间才能找到如何使用查询参数发出GET请求的方法),但是如果您已经在使用Spray,这是一个不错的选择。而且文档比调度更好。

我们使用它在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
Henry H.

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)

@Andrea-尝试以下链接:flotsam.nl/dispatch-periodic-table.html。目前看来dispatch作者在主要文档上存在一些问题-就在昨天,这些文档要好得多。
罗加奇

@Rogach不仅仅是为了旧派遣吗?安德里亚(Andrea):更新了我的帖子,并提供了相关信息的链接
德雷辛(Drexin)2012年

它现在可以:val svc = url("http://diasporafoundation.org/").POST.setBody("test")
VasiliNovikov 2013年


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

很棒的Li,我也有一个疑问,如果我想给Json提供request.post中的数据该怎么办,我是否必须提取每个键值对。有没有简单的方法。
Mohammad Rijwan '19

我明白了,val json =“”“ {” key“:” value“}”“”。stripMargin val r = requests.post(url,data = json)val json = ujson.read(r.text()) println(json)
Mohammad Rijwan

2

如果我可以制作一个无耻的插件,那么我有一个名为Bee-Client的API ,它只是Scala中Java HttpUrlConnection的包装。


谢谢。有没有可用的文档?
安德里亚(Andrea)

是的,但是它仍然很有限。我正在研究一些示例用法。现在,看看测试代码,尤其是集成测试bitbucket.org/rickb777/lighthttpclient/src/a6c526e4684b/src/...
里克-777


好!但这似乎是私人的。我目前没有我的Bitbucket凭据。您可能忘记了将该Wiki标记为公开
Andrea

抱歉 我将文档移到了我的Web服务器上:bigbeeconsultants.co.uk/light-http-client我也扩展了文档。
Rick-777


1

我必须做同样的事情来测试一个端点(在集成测试中)。因此,以下是在Scala中从GET请求获取响应的代码。我正在使用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请求。不带参数的GET-带参数的POST我使用它与StreamSet进行通信,以启动管道或检查管道状态。

它仅需要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"
    }
  }

}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.