akka HttpResponse 将正文读取为字符串 scala
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32315789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
akka HttpResponse read body as String scala
提问by tg44
So I have a function with this signature (akka.http.model.HttpResponse):
所以我有一个带有这个签名的函数(akka.http.model.HttpResponse):
def apply(query: Seq[(String, String)], accept: String): HttpResponse
I simply get a value in a test like:
我只是在测试中得到一个值,例如:
val resp = TagAPI(Seq.empty[(String, String)], api.acceptHeader)
I want to check its body in a test something like:
我想在测试中检查它的身体,例如:
resp.entity.asString == "tags"
My question is how I can get the response body as string?
我的问题是如何将响应正文作为字符串获取?
采纳答案by user3548738
import akka.http.scaladsl.unmarshalling.Unmarshal
implicit val system = ActorSystem("System")
implicit val materializer = ActorFlowMaterializer()
val responseAsString: Future[String] = Unmarshal(entity).to[String]
回答by Konrad 'ktoso' Malawski
Since Akka Http is streams based, the entity is streaming as well. If you really need the entire string at once, you can convert the incoming request into a Strictone:
由于 Akka Http 是基于流的,因此实体也是流的。如果您真的一次需要整个字符串,您可以将传入的请求转换为Strict一个:
This is done by using the toStrict(timeout: FiniteDuration)(mat: Materializer)API to collect the request into a strict entity within a given time limit (this is important since you don't want to "try to collect the entity forever" in case the incoming request does actually never end):
这是通过使用toStrict(timeout: FiniteDuration)(mat: Materializer)API 在给定的时间限制内将请求收集到严格实体中来完成的(这很重要,因为您不想“尝试永远收集实体”,以防传入的请求实际上永远不会结束):
import akka.stream.ActorFlowMaterializer
import akka.actor.ActorSystem
implicit val system = ActorSystem("Sys") // your actor system, only 1 per app
implicit val materializer = ActorFlowMaterializer() // you must provide a materializer
import system.dispatcher
import scala.concurrent.duration._
val timeout = 300.millis
val bs: Future[ByteString] = entity.toStrict(timeout).map { _.data }
val s: Future[String] = bs.map(_.utf8String) // if you indeed need a `String`
回答by Shashank Jain
You can also try this one also.
你也可以试试这个。
responseObject.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String) map println
回答by J. Nadberezny
Unmarshaller.stringUnmarshaller(someHttpEntity)
works like a charm, implicit materializer needed as well
像魅力一样工作,也需要隐式物化器
回答by Shendor
Unfortunately in my case, Unmarshalto String didn't work properly complaining on: Unsupported Content-Type, supported: application/json. That would be more elegant solution, but I had to use another way. In my test I used Future extracted from entity of the response and Await (from scala.concurrent) to get the result from the Future:
不幸的是,在我的情况下,Unmarshalto String 无法正常工作,抱怨:Unsupported Content-Type, supported: application/json。那将是更优雅的解决方案,但我不得不使用另一种方式。在我的测试中,我使用从响应实体中提取的 Future 和 Await(来自 scala.concurrent)从 Future 中获取结果:
Put("/post/item", requestEntity) ~> route ~> check {
val responseContent: Future[Option[String]] =
response.entity.dataBytes.map(_.utf8String).runWith(Sink.lastOption)
val content: Option[String] = Await.result(responseContent, 10.seconds)
content.get should be(errorMessage)
response.status should be(StatusCodes.InternalServerError)
}
If you need to go through all lines in a response, you can use runForeachof Source:
如果您需要查看响应中的所有行,您可以使用runForeachSource:
response.entity.dataBytes.map(_.utf8String).runForeach(data => println(data))
回答by Alexander Kondaurov
Here is simple directive that extracts stringfrom request's body
这是string从请求正文中提取的简单指令
def withString(): Directive1[String] = {
extractStrictEntity(3.seconds).flatMap { entity =>
provide(entity.data.utf8String)
}
}
回答by u5827450
Here is my working example,
这是我的工作示例,
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.util.ByteString
import scala.concurrent.Future
import scala.util.{ Failure, Success }
def getDataAkkaHTTP:Unit = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val url = "http://localhost:8080/"
val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = url))
responseFuture.onComplete {
case Success(res) => {
val HttpResponse(statusCodes, headers, entity, _) = res
println(entity)
entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach (body => println(body.utf8String))
system.terminate()
}
case Failure(_) => sys.error("something wrong")
}
}

