akka HttpResponse lire le corps comme chaîne scala

J'ai Donc une fonction avec cette signature (akka.http.modèle.HttpResponse):

def apply(query: Seq[(String, String)], accept: String): HttpResponse

J'obtiens simplement une valeur dans un test comme:

val resp = TagAPI(Seq.empty[(String, String)], api.acceptHeader)

Je veux vérifier son corps dans un test quelque chose comme:

resp.entity.asString == "tags"

Ma question Est de savoir comment obtenir le corps de réponse en tant que chaîne?

21
demandé sur tg44 2015-08-31 19:28:43

6 réponses

  import akka.http.scaladsl.unmarshalling.Unmarshal


  implicit val system = ActorSystem("System")  
  implicit val materializer = ActorFlowMaterializer() 

  val responseAsString: Future[String] = Unmarshal(entity).to[String]
21
répondu user3548738 2016-04-10 20:03:13

Comme Akka Http est basé sur des flux, L'entité est également en streaming. Si vous avez vraiment besoin de la chaîne entière à la fois, vous pouvez convertir la requête entrante en Strict Un:

Ceci est fait en utilisant l'API toStrict(timeout: FiniteDuration)(mat: Materializer) pour collecter la requête dans une entité stricte dans un délai donné (ceci est important car vous ne voulez pas "essayer de collecter l'entité pour toujours" au cas où la requête entrante ne finirait jamais):

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`
19
répondu Konrad 'ktoso' Malawski 2015-09-02 21:11:07

Vous pouvez également essayer celui-ci aussi.

responseObject.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String) map println
5
répondu Shashank Jain 2017-07-27 03:15:47

Malheureusement dans mon cas, Unmarshal to String n'a pas fonctionné correctement en se plaignant de: Unsupported Content-Type, supported: application/json. Ce serait une solution plus élégante, mais je devais utiliser un autre moyen. Dans mon test, J'ai utilisé Future extrait de l'entité de la réponse et Await (de scala.concurrent) pour obtenir le résultat du futur:

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)
    }

Si vous devez parcourir toutes les lignes d'une réponse, vous pouvez utiliser runForeach de Source:

 response.entity.dataBytes.map(_.utf8String).runForeach(data => println(data))
1
répondu Shendor 2016-12-30 16:42:35

Voici mon exemple de travail,

  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")
    }


  }
0
répondu Charlie 木匠 2018-06-28 21:18:56
Unmarshaller.stringUnmarshaller(someHttpEntity)

Fonctionne comme un charme, le matérialiseur implicite est également nécessaire

0
répondu J. Nadberezny 2018-07-11 12:32:26