所以我有一个带有这个签名的函数(akka.http.model.HttpResponse):
def apply(query: Seq[(String, String)], accept: String): HttpResponse
我只是在测试中得到一个值,如:
val resp = TagAPI(Seq.empty[(String, String)], api.acceptHeader)
我想在测试中查看它的主体:
resp.entity.asString == "tags"
我的问题是如何将响应主体作为字符串?
答案 0 :(得分:23)
import akka.http.scaladsl.unmarshalling.Unmarshal
implicit val system = ActorSystem("System")
implicit val materializer = ActorFlowMaterializer()
val responseAsString: Future[String] = Unmarshal(entity).to[String]
答案 1 :(得分:22)
由于Akka Http是基于流的,因此实体也是流式传输。如果您确实需要一次完整的字符串,则可以将传入的请求转换为Strict
个:
这是通过使用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`
答案 2 :(得分:7)
您也可以尝试这个。
responseObject.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String) map println
答案 3 :(得分:1)
不幸的是,在我的情况下,Unmarshal
到字符串无法正常抱怨: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)
}
如果您需要浏览回复中的所有行,可以使用runForeach
来源:
response.entity.dataBytes.map(_.utf8String).runForeach(data => println(data))
答案 4 :(得分:1)
这是我的工作示例,
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")
}
}
答案 5 :(得分:1)
Unmarshaller.stringUnmarshaller(someHttpEntity)
工作就像一个魅力,也需要隐式实现器
答案 6 :(得分:0)
这是一个简单的指令,可从请求的正文中提取string
def withString(): Directive1[String] = {
extractStrictEntity(3.seconds).flatMap { entity =>
provide(entity.data.utf8String)
}
}