【问题标题】:Doing HTTP request in Scala在 Scala 中执行 HTTP 请求
【发布时间】:2012-07-30 10:11:03
【问题描述】:

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

似乎Dispatch 是用于此任务的标准库,但我找不到它的文档。我在上面链接的主站点详细解释了什么是承诺以及如何进行异步编程,但实际上并未记录 API。有一个periodic table - 看起来有点吓人 - 但它似乎只对已经知道该怎么做并且只需要提示神秘语法的人有用。

似乎也是Scalaz has some facility for HTTP,但我也找不到任何文档。

【问题讨论】:

  • 感谢您提供 API。从中我可能能够弄清楚如何实际使用该库。不过,我想要一些中间的东西,比如 API 的高级描述。我想像“要发出 POST 请求,你使用这个构造函数,带有这些参数等等”。
  • 同意 Dispatch 可以使用更好的文档。我认为您现在最好的选择是在 Google 群组中提问:groups.google.com/forum/#!forum/dispatch-scala

标签: http scala scalaz


【解决方案1】:

我使用以下代码: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 及其特殊语法的原因
  • 注意:默认连接超时时间非常低(100 毫秒),因此如果您收到java.net.SocketTimeoutException: connect timed out,则添加一行如.option(HttpOptions.connTimeout(10000))
  • 它不再与 scala 2.11 兼容,因为他们删除了 ScalaObject。热切地等待 scalaj-http 更新他们的库。
  • @Dalvik 我认为他们已经清理了他们的游戏;只需将 "org.scalaj" %% "scalaj-http" % "1.1.4" 添加到 build.sbt。
  • 我不确定其他人是否无法在帖子中获得“asParamsMap”的响应,但我最终不得不使用“asString”,然后使用 net.minidev.json 显式解析。 parser.JSONParser.
【解决方案2】:

您可以使用spray-client。缺少文档(我花了一些时间才找到how to make GET requests with query parameters),但如果您已经在使用喷雾,这是一个不错的选择。而且文档比调度好。

我们在AI2 上使用它而不是dispatch,因为运算符的符号性较低,而且我们已经在使用喷雾/演员。

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)

【讨论】:

  • 主要的 spray 开发人员转移到 akka,因此即使该 spray 已准备好生产,也将过时,AKKA-HTTP 和 AKKA-STREAMS 将成为下一轮 http 客户端和服务器。 akka.io/docs
【解决方案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")

【讨论】:

  • Awesome Li,我也有一些疑问,如果我想给requests.post中的数据提供Json,我必须提取每个键值对吗?有没有简单的办法。
  • 我明白了,val json = """{"key":"value"}""".stripMargin val r = requests.post(url,data=json) val json = ujson.读取(r.text()) println(json)
【解决方案4】:

我正在使用调度: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 不只是为了旧的调度吗?安德里亚:更新了我的帖子并提供了源链接
  • 现在可以了:val svc = url("http://diasporafoundation.org/").POST.setBody("test")
【解决方案5】:

另一个选项是 Typesafe 的 play-ws,它是将 Play Framework WS 库分解为一个独立的库:

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

我不一定会将此作为最佳选择,但值得一提。

【讨论】:

    【解决方案6】:

    如果我能做一个无耻的插件,我有一个名为 Bee-Client 的 API,它只是 Scala 中用于 Java 的 HttpUrlConnection 的包装器。

    【讨论】:

    【解决方案7】:

    我必须做同样的事情来测试一个端点(在集成测试中)。因此,以下是从 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)
      }
    

    【讨论】:

      【解决方案8】:

      为什么不使用 Apache HttpComponents ?这是application FAQ,它涵盖了广泛的场景。

      【讨论】:

      • 我可能会使用它,但我会更乐意学习一个更惯用的工具
      【解决方案9】:

      这是我正在学习的一门课程。它有 GET 和 POST 请求。 不带参数的 GET - 带参数的 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"
          }
        }
      
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-02
        • 1970-01-01
        • 2017-09-27
        • 2013-02-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多