我需要一个成熟的 HTTP 客户端库,它对 scala 来说是惯用的,使用简洁,语义简单。我查看了 Apache HTTP 和 Scala Dispatch 以及许多承诺惯用 Scala 包装的新库。Apache HTTP 客户端确实需要冗长,而 Dispatch 很容易混淆。
什么是适合 Scala 使用的 HTTP 客户端?
我最近开始使用Dispatch,有点神秘(很棒的一般介绍,严重缺乏基于场景/用例的详细文档)。Dispatch 0.9.1 是 Ning 的Async Http Client的 Scala 包装器;要完全了解正在发生的事情,需要将自己介绍给那个图书馆。在实践中,我真正需要查看的唯一东西是RequestBuilder——其他一切都很好地融入了我对 HTTP 的理解。
我给 0.9 版本一个坚实的大拇指(到目前为止!)非常简单地完成工作......一旦你超越了最初的学习曲线。
Dispatch 的 Http“构建器”是不可变的,并且似乎在线程环境中运行良好。虽然我在文档中找不到任何说明它是线程安全的;对来源的一般阅读表明它是。
请注意RequestBuilder是可变的,因此不是线程安全的。
以下是我发现有用的一些附加链接:
我找不到 0.9.* 版本的 ScalaDoc 链接,所以我浏览了0.9.* 版本的源代码;
ScalaDoc 0.8 版本;与0.9大不相同的野兽(今天)。
运营商的“定期”表,也与 0.8 相关。
较早的0.8 版“dispatch-classic”文档帮助我了解了他们如何使用 url 构建器,并提供了一些关于如何将事物联系在一起的提示,这些提示确实可以延续到 0.9。
Dispatch 和其他一些库不再维护。目前唯一严重的是spray-client和Play!WS。
spray-client的语法有点晦涩难懂。play-ws很容易使用:
(build.sbt)
libraryDependencies += "com.typesafe.play" %% "play-ws" % "2.4.3"
(基本用法)
val wsClient = NingWSClient()
wsClient
.url("http://wwww.something.com")
.get()
.map { wsResponse =>
// read the response
}
这里的聚会有点晚了,但我对spray-client印象深刻。
它有一个很好的 DSL 用于构建请求,支持同步和异步执行,以及各种(非)编组类型(JSON、XML、表单)。它也与Akka配合得很好。
二在最初回复这篇文章六年后,我会有不同的答案。
我一直在使用akka-http,这是 spray 和 akka 团队之间的合作。它由 Lightbend 提供支持,与 akka 异步环境紧密结合……它是完成这项工作的正确工具。
sttp是我们一直在等待的 Scala HTTP 库!
它有一个流畅的 DSL 用于形成和执行请求(来自其 README 的代码示例):
val request = sttp
.cookie("session", "*!@#!@!$")
.body(file) // of type java.io.File
.put(uri"http://httpbin.org/put")
.auth.basic("me", "1234")
.header("Custom-Header", "Custom-Value")
.response(asByteArray)
它通过可插入后端支持同步、异步和流式调用,包括 Akka-HTTP(以前的 Spray)和古老的 AsyncHttpClient(Netty):
implicit val sttpHandler = AsyncHttpClientFutureHandler()
val futureFirstResponse: Future[Response[String]] = request.send()
它支持scala.concurrent.Future
、scalaz.concurrent.Task
、monix.eval.Task
和cats.effect.IO
- 所有主要的 Scala IO monad 库。
此外,它还有一些额外的技巧:
它具有请求和响应的案例类表示(尽管它没有例如强类型标头): https ://github.com/softwaremill/sttp/blob/master/core/src/main/scala /com/softwaremill/sttp/RequestT.scala https://github.com/softwaremill/sttp/blob/master/core/src/main/scala/com/softwaremill/sttp/Response.scala
它提供了一个URI 字符串插值器:
val test = "chrabąszcz majowy"
val testUri: Uri = uri"http://httpbin.org/get?bug=$test"
import com.softwaremill.sttp.circe._
val response: Either[io.circe.Error, Response] =
sttp
.post(uri"...")
.body(requestPayload)
.response(asJson[Response])
.send()
最后,它由 softwaremill 的可靠人员维护,并且有很好的文档。
在与 Apache 客户端有过一些不愉快的经历后,我开始编写自己的客户端。内置的 HttpURLConnection 被广泛认为是错误的。但这不是我的经验。事实上,情况正好相反,Apache 客户端的线程模型有些问题。自 Java6(或 5?)以来,HttpURLConnection 提供了高效的 HTTP1.1 连接,其中内置了 keep-alive 等基本功能,并且它可以轻松处理并发使用。
因此,为了弥补 HttpURLConnection 提供的 API 带来的不便,我开始着手在 Scala 中编写一个新的 API,作为一个开源项目。它只是 HttpURLConnection 的包装器,但与 HttpURLConnection 不同,它旨在易于使用。与 Apache 客户端不同,它应该很容易融入现有项目。与 Dispatch 不同,它应该易于学习。
它被称为蜜蜂客户端
我为无耻的插头道歉。:)
除了 Dispatch 外,没有太多内容。scalaz曾尝试构建功能性 http 客户端。但是它已经过时了一段时间,在 scalaz7 分支中没有它的版本。此外,playframework 中还有一个有用的 ning async-http-client包装器。在那里你可以做这样的电话:
WS.url("http://example.com/feed").get()
WS.url("http://example.com/item").post("content")
如果你不使用 play,你可以使用这个 API 作为灵感!在您的项目中并且不喜欢 Dispatch API。
喷
你真的应该考虑使用Spray。在我看来,它有一些复杂的语法,但如果你的目标是构建一个高性能的 http 客户端,它仍然非常有用。使用 Spray 的主要优点是它基于akka actor 库,具有极强的可扩展性和强大的功能。conf
您可以通过仅更改文件将您的 http 客户端扩展到多台机器。
此外,几个月前 Spray 加入了 Typesafe,据我了解,它将成为基本 akka 发行版的一部分。证明
播放2
另一种选择是 Play2 WS 库使用 ( doc )。据我所知,它还没有从 Play 发行版中分离出来,但由于它非常简单,值得花一些时间附加整个 Play 框架来获得那部分。为其提供配置存在一些问题,因此这对于丢弃和用例来说并不是很好。然而,我们在一些非基于 Play 的项目中使用了它,一切都很好。
ScalaJ-Http 是一个非常简单的同步 http 客户端
https://github.com/scalaj/scalaj-http
如果您需要一个没有仪式的准系统 Scala 客户端,我会推荐它。
很惊讶这里没有人提到 finagle。使用起来超级简单:
import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.http
import com.twitter.util.{Await, Future}
object Client extends App {
val client: Service[http.Request, http.Response] = Http.newService("www.scala-lang.org:80")
val request = http.Request(http.Method.Get, "/")
request.host = "www.scala-lang.org"
val response: Future[http.Response] = client(request)
Await.result(response.onSuccess { rep: http.Response =>
println("GET success: " + rep)
})
}
有关更多详细信息,请参阅快速入门指南:https ://twitter.github.io/finagle/guide/Quickstart.html
我使用过 Dispatch、Spray Client 和 Play WS Client Library……它们都不是简单的使用或配置。所以我创建了一个更简单的 HTTP 客户端库,它可以让您在简单的单行中执行所有经典的 HTTP 请求。
看一个例子:
import cirrus.clients.BasicHTTP.GET
import scala.concurrent.Await
import scala.concurrent.duration._
object MinimalExample extends App {
val html = Await.result(Cirrus(GET("https://www.google.co.uk")), 3 seconds)
println(html)
}
...产生...
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-GB">...</html>
该库称为 Cirrus,可通过 Maven Central 获得
libraryDependencies += "com.github.godis" % "cirrus_2.11" % "1.4.1"
文档在 GitHub 上可用
https://github.com/Godis/Cirrus