Scala и Akka HTTP: запрос внутри запроса и проблема с потоками - PullRequest
5 голосов
/ 05 апреля 2020

Я новичок в изучении Scala, Akka Streams и Akka HTTP, поэтому заранее извиняюсь, если вопрос слишком базовый c.

Я хочу сделать HTTP-запрос внутри HTTP-запроса, просто как в следующем фрагменте кода:

  implicit val system = ActorSystem("ActorSystem")
  implicit val materializer = ActorMaterializer
  import system.dispatcher

  val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].map {
    case HttpRequest(HttpMethods.GET, Uri.Path("/api"), _, _, _) =>
      val responseFuture = Http().singleRequest(HttpRequest(uri = "http://www.google.com"))
      responseFuture.onComplete {
        case Success(response) =>
          response.discardEntityBytes()
          println(s"The request was successful")
        case Failure(ex) =>
          println(s"The request failed with: $ex")
      }
      //Await.result(responseFuture, 10 seconds)
      println("Reached HttpResponse")
      HttpResponse(
        StatusCodes.OK
      )
  }

  Http().bindAndHandle(requestHandler, "localhost", 8080)  

Но в приведенном выше случае результат выглядит следующим образом, то есть Reached HttpResponse достигается первым до завершения запроса:

Reached HttpResponse
The request was successful

Я попытался использовать Await.result(responseFuture, 10 seconds) (в настоящее время закомментировано), но это не имело никакого значения.

Что мне здесь не хватает? Любая помощь будет принята с благодарностью!

Большое спасибо заранее!

1 Ответ

2 голосов
/ 05 апреля 2020

map - это функция, которая принимает запрос и выдает ответ:

HttpRequest => HttpResponse

Сложность заключается в том, что ответ имеет тип Future. Следовательно, вам нужна функция, которая справляется с этим. Функция, которая принимает HttpRequest и возвращает Future of HttpResponse.

HttpRequest => Future[HttpResponse]

И вуаля, mapAsyn c - это именно то, что вам нужно:

val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].mapAsync(2) {
  case HttpRequest(HttpMethods.GET, Uri.Path("/api"), _, _, _) =>
    Http().singleRequest(HttpRequest(uri = "http://www.google.com")).map (resp => {
      resp.discardEntityBytes()
      println(s"The request was successful")
      HttpResponse(StatusCodes.OK)
    })
}
...