使用Akka-Streams HTTP将整个HttpResponse主体作为String获取 [英] Get whole HttpResponse body as a String with Akka-Streams HTTP
问题描述
我正在尝试了解如何使用新的 akka.http
库。我想向服务器发送一个http请求并将整个响应正文作为单个字符串读取,以便生成 Source [String,?]
。
I'm trying to understand how to use the new akka.http
library. I would like to send an http request to a server and read the whole response body as a single String in order to produce a Source[String,?]
.
这是迄今为止我能够制作的最佳解决方案:
Here is the best solution I was able to produce so far:
def get(
modelID: String,
pool: Flow[(HttpRequest,Int),(Try[HttpResponse],Int),Http.HostConnectionPool]
): Source[String,Unit] = {
val uri = reactionsURL(modelID)
val req = HttpRequest(uri = uri)
Source.single( (req,0) )
.via( pool )
.map {
case (Success(resp),_) =>
resp.entity.dataBytes.map( _.decodeString("utf-8") )
}.flatten(FlattenStrategy.concat)
.grouped( 1024 )
.map( _.mkString )
它似乎运行良好(除了缺少的错误路径),但它是这些简单的任务有点笨拙。有更聪明的解决方案吗?我可以避免分组
/ mkString
?
It seems to work well (except the missing error path), but it is a bit clunky for such simple tasks. Is there a smarter solution ? Can I avoid the grouped
/mkString
?
推荐答案
你可以使用 HttpResponse 。它将整个答案收集为Future。
You can use toStrict method of HttpResponse with timeout. It gathers whole answer as Future.
def toStrict(timeout:FiniteDuration)(隐式ec:ExecutionContext,fm:Materializer):Future [Strict ]返回带有严格实体的此消息的可共享且可序列化的
def toStrict(timeout: FiniteDuration)(implicit ec: ExecutionContext, fm: Materializer): Future[Strict] Returns a sharable and serializable
副本。
示例:
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpResponse, HttpRequest}
import akka.stream.{Materializer, ActorMaterializer}
import akka.stream.scaladsl.{Sink, Flow, Source}
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration._
import scala.util.{Try, Success}
object Main extends App {
implicit val system = ActorSystem()
import system.dispatcher
implicit val materializer = ActorMaterializer()
val host = "127.0.0.1"
lazy val pool = Http().newHostConnectionPool[Int](host, 9000)
FlowBuilder.get("/path", pool).to(Sink.foreach(_.foreach(println))).run()
}
object FlowBuilder {
def get(modelID: String, pool: Flow[(HttpRequest, Int), (Try[HttpResponse], Int), Http.HostConnectionPool])
(implicit ec: ExecutionContext, mat: Materializer): Source[Future[String], Unit] = {
val uri = modelID
val req = HttpRequest(uri = modelID)
Source.single((req, 0)).via(pool)
.map {
case (Success(resp), _) => resp.entity.toStrict(5 seconds).map(_.data.decodeString("UTF-8"))
}
}
}
这篇关于使用Akka-Streams HTTP将整个HttpResponse主体作为String获取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!