だから私はこのシグネチャを持つ関数を持っています(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"
私の質問は、応答本文を文字列として取得する方法ですか?
import akka.http.scaladsl.unmarshalling.Unmarshal
implicit val system = ActorSystem("System")
implicit val materializer = ActorFlowMaterializer()
val responseAsString: Future[String] = Unmarshal(entity).to[String]
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`
これも試してみてください。
responseObject.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String) map println
リクエストの本文からstring
を抽出する簡単なディレクティブを次に示します。
def withString(): Directive1[String] = {
extractStrictEntity(3.seconds).flatMap { entity =>
provide(entity.data.utf8String)
}
}
Unmarshaller.stringUnmarshaller(someHttpEntity)
チャームのように機能し、暗黙のマテリアライザーも必要です
これが私の実例です。
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")
}
}
残念ながら、私の場合、StringへのUnmarshal
は正しく動作しませんでした:Unsupported Content-Type, supported: application/json
。それはよりエレガントなソリューションになりますが、別の方法を使用する必要がありました。私のテストでは、応答のエンティティから抽出されたFutureとAcal(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))