首页 > 解决方案 > AkkaHTTP:从 HttpEntity 中获取内容

问题描述

我正在使用 Scala 中的 AkkaHTTP,尝试与 API 交互,但我在通过某些 API 调用获取数据时遇到了一些麻烦。基本上,我有一个 curl 命令,它在我的终端中适用于对该特定 API 的任何有效 API 调用,但在我当前的代码中,我只获得响应足够小的调用的实际数据。

我的第一次尝试是使用 sys.process._ 和 !! 使用 "curl (url) -X GET -H \"Authorization: Bearer (auth token)\" (这是在我的终端中工作的命令)的字符串上的方法,但由于解析问题而在 scala 中失败并出现错误标头;因此在没有取得进展并意识到无论如何我都想使用 AkkaHTTP 之后,我放弃了这种方法并来到下面的代码,我从另一个 stackoverflow 帖子中借用了它的格式。

implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher

val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(
  uri = "(url)").withHeaders(
  RawHeader("Authorization", "Bearer (auth token)")
))


responseFuture
  .onComplete {
    case Success(res) => println(res)
    case Failure(_)   => "failure"
  }

现在,我已经在两个不同的 API 调用上进行了尝试;第一个在我的终端中返回一个包含 327 个字符的 JSON 字符串,它返回一个 blob,其中 res.entity 是 HttpEntity.Strict(application/json,(与终端中相同的 JSON blob))。然而,虽然第二个调用在我的终端中返回一个包含 203,413 个字符(比第一个大得多)的 JSON blob,但在 scala 中发送该请求会返回一个 blob,其中 res.entity 只是 HttpEntity.Chunked(application/json)。我假设有效载荷被分成多个数据包(“Chunked”是该场景的一个相当适用的名称),但我似乎无法弄清楚如何从这里获取有效载荷信息,我希望能得到一些帮助。

标签: scalaakka-http

解决方案


如果可以将整个实体加载到内存中,则可以toStrict调用ResponseEntity

import scala.concurrent.Future
import scala.concurrent.duration._

val entityFut: Future[String] =
  responseFuture.flatMap(_.entity.toStrict(5 seconds).map(_.data.utf8String))

entityFut.onComplete {
  case Success(body) =>
    println(body)
  case Failure(_) =>
    println("failure")
}

您还可以使用内置的unmarshaller

import akka.http.scaladsl.unmarshalling.Unmarshal

val entityFut: Future[String] =
  responseFuture.flatMap(resp => Unmarshal(resp.entity).to[String])

推荐阅读