как может иметь тело http response spray scala

Я хочу получить содержимое result.entity.asString, но результат пуст. И у меня есть много WARNING, которые делают нон-стоп. Мой код: `

implicit  val system: ActorSystem = ActorSystem("simple-spray-client")
val log: LoggingAdapter = Logging(system, getClass)
val pipeline: SendReceive = sendReceive
val responseFuture: Future[HttpResponse] = pipeline {
Get("https://api.guildwars2.com/v2/items")
}
val re = responseFuture.onComplete {
case Success(result: HttpResponse) => {
  result.entity.asString
  shutdown()
 }
 case Failure(error) =>
  log.error(error, "Couldn't get list of items")
  shutdown()
}


def shutdown(): Unit = {
 IO(Http).ask(Http.CloseAll)(1.second).await
 system.shutdown()
}}

` результат:

()
[WARN] [10/27/2015 11:26:04.776] [simple-spray-client-akka.actor.default-dispatcher-4] [akka://simple-spray-client/user/IO-HTTP/group-0/0] Illegal  response header: Illegal 'Cache-Control' header: Invalid input '"', expected  $timesCache$minusControl (line 1, pos 1):
"public, max-age=300"
 ^
 [WARN] [10/27/2015 11:26:04.779] [simple-spray-client-akka.actor.default- dispatcher-4] [akka://simple-spray-client/user/IO-HTTP/group-0/0] Illegal response header: Illegal 'Access-Control-Expose-Headers' header: Invalid input '"', expected  $timesAccess$minusControl$minusExpose$minusHeaders (line 1, pos 1):
 "X-Result-Total, X-Result-Count"
  ^

person timo 123    schedule 27.10.2015    source источник


Ответы (4)


Как насчет очистки кода и форматирования для начала? :) (responseFuture.toString? println(re)?). Это, безусловно, поможет привлечь ответы.

При этом запрос инициируется спреем. Предупреждения касаются заголовков в ответе. Я выполнил запрос, и заголовки ответа:

Cache-Control: "public, max-age=300" 
Transfer-Encoding: chunked 
Content-Type: application/json; charset=utf-8 
Content-Encoding: gzip 
Content-Language: en 
Expires: Tue, 27 Oct 2015 11:44:47 +0000 
Vary: Accept-Encoding 
Server: Microsoft-IIS/7.5 
X-Result-Total: 48798
X-Result-Count: 48798
Access-Control-Expose-Headers: "X-Result-Total, X-Result-Count"
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
Date: Tue, 27 Oct 2015 11:39:47 GMT 

Как видите, значения для Cache-Control и Access-Control-Expose-Headers начинаются с двойной кавычки, как и предупреждает спрей.

Теперь вы можете попробовать повторно реализовать как

pipeline {
    Get("https://api.guildwars2.com/v2/items")
}.onComplete {

    case Success(result: HttpResponse) => 
        log.info("Result: "+result.entity.asString)
        shutdown()

    case Failure(error) =>
        log.error(error, "Couldn't get list of items")
        shutdown()
}

... и посмотрите, что записывается на информационном уровне на вашей консоли (не уверен, какую структуру ведения журнала вы используете)

Кроме того, хорошей идеей может быть проверка кодов ответов HTTP перед доступом к объекту.

person Bruno Grieder    schedule 27.10.2015
comment
Я хочу использовать результат result.entity.asString в другом классе, поэтому мне нужно значение, а не отображать результат. - person timo 123; 27.10.2015

Я отслеживаю сообщения журнала, которыми вы поделились, и делаю get запрос к URL-адресу API. Здесь это заголовки ответов;

Вы можете видеть, что Cache-Control и Access-Control-Expose-Headers имеют двойную кавычку "..", на которую указывает сообщение журнала.

Я думаю, что вы должны сначала проверить http status code, который помогает увидеть основную проблему.

введите здесь описание изображения

person Fatih Donmez    schedule 27.10.2015

как я понял вы хотите:

import scala.concurrent.Await
import scala.concurrent.duration._
        def extract(responseFuture: Future[HttpResponse]): HttpResponse = Await.result(responseFuture, xx.seconds)

а также

val myOlolo = extract(responseFuture).entity.asString
person Александр Третьяк    schedule 10.03.2016

Либо вы можете иметь ламбады onSuccess и onFailure, как это предлагается в других ответах, и передать success value в нужный вам класс, что, по-видимому, вас беспокоит.

class ItemServer {

    def callServer() : Unit = {
      val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
      val response: Future[HttpResponse] = pipeline(Get("https://api.guildwars2.com/v2/items"))

      response.onComplete {
        case Success(response : HttpResponse) => new SomeService().doSomething(response.entity.asString)
        case Failure(error) => new SomeService().doSomethingElse(error.getMessage)
      }
    }

}

class SomeService {
  def doSomething(bodyString: String): Unit = {
    val cleanupResponse  = bodyString.replaceAll("\n", "")
    val bodyAsList = cleanupResponse.substring(1, cleanupResponse.length).split(",").toList
    println(bodyAsList)
  }

  def doSomethingElse(bodyString: String): Unit = {
    println(bodyString)
  }
}

Или вы можете заблокировать, пока не будет получен ответ, а затем использовать ответ, чтобы делать все, что вы хотите, как показано в тесте ниже:

class ItemServerTests extends FunSpec with BeforeAndAfterEach {
   describe("/items") {
    it("responds with success message") {
      val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
      val response: Future[HttpResponse] = pipeline(Get("https://api.guildwars2.com/v2/items"))

      val bodyString = Await.result(response, Duration("10 seconds")).entity.asString.trim
      new SomeService().doSomething(bodyString)
    }
  }
}


class SomeService {
  def doSomething(bodyString: String): Unit = {
    val cleanupResponse = bodyString.replaceAll("\n", "")
    val bodyAsList = cleanupResponse.substring(1, cleanupResponse.length).split(",").toList
    assert(bodyAsList.size == 55372)
  }
}
person prayagupd    schedule 09.01.2017