在 Scala 中执行 HTTP 请求

我试图向一个在 Scala 中返回一些 XML 的 webservice 发出一个简单的 POST 请求。

看起来 调度中心是用于这个任务的标准库,但是我找不到有关它的文档。我在上面链接的主站点详细解释了什么是承诺以及如何进行异步编程,但实际上并没有记录 API。有一个 元素周期表——看起来有点吓人——但它似乎只对那些已经知道该做什么并且只需要提醒就能了解隐晦语法的人有用。

它似乎也是 Scalaz 对 HTTP 有一些功能,但我也找不到任何有关它的文档。

125646 次浏览

为什么不使用 Apache HttpComponent? 下面是 申请常见问题,它涵盖了广泛的场景。

我使用以下代码: 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"

我正在使用调度: 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

如果我可以做一个无耻的插件,我有一个名为 蜜蜂客户的 API,它只是一个用于 Java 的 HttpUrlConnection 的 Scala 包装器。

你可以用 喷雾客户端。文档是缺乏的(它花了我一些挖掘找出 如何使用查询参数发出 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)

另一个选项是 Typesafe 的 Play-WS,它是 Play Framework WS 库,作为一个独立的库:

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

我不一定认为这是最好的选择,但值得一提。

我必须做同样的事情来测试一个终点(在集成测试中)。下面是在 Scala 中从 GET 请求获取响应的代码。 我使用 scala.io.Source 从端点读取 json 到对象转换的 ObjectMapper。

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

下面是我正在研究的一个类,它同时包含 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"
}
}


}


使用我的 请求-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")