Акка Http.Преобразовать ответ API и переслать его - PullRequest
0 голосов
/ 29 мая 2018

У меня есть маршрут Akka-Http, где я вызываю Bing Search API.Я хочу добавить несколько дополнительных записей в результат, прежде чем отправлять ответ клиенту.Я использую Circe для обработки JSON.Вот код, который не работает, но иллюстрирует идею:

    val extraData = Map("key1"->"value1","key2"->"val2").asJson

    val query = URLEncoder.encode(q, "utf8")

    val responseFuture: Future[HttpResponse] = Http().singleRequest(
      HttpRequest(uri = "https://api.cognitive.microsoft.com/bing/v7.0/search?q=" + query)
        .withHeaders(RawHeader("Ocp-Apim-Subscription-Key", k1)))

    val alteredResponse = responseFuture.map{ response => {
      response.entity.toStrict(2 seconds) flatMap { e =>
        e.dataBytes
          .runFold(ByteString.empty) { case (acc, b) => acc ++ b }
          .map(k => parse(k.utf8String)
          match {
            case Left(failure) => "Can't parse"
            case Right(json) => Try {
              json.hcursor.withFocus{
                _.mapObject(x =>
                  x.add("extraData",extraData)
                )
              }
            }}
          )
      }
    }}

    complete(alteredResponse)

Это хороший подход?Как я могу заставить его работать?

1 Ответ

0 голосов
/ 29 мая 2018

Я закончил тем, что использовал flatMap и создал объект HttpResponse вручную:

    val responseFuture: Future[HttpResponse] = Http().singleRequest(
      HttpRequest(uri = "https://api.cognitive.microsoft.com/bing/v7.0/search?q=" + query)
        .withHeaders(RawHeader("Ocp-Apim-Subscription-Key", k1)))
      .flatMap{ response => {
        response.entity.toStrict(2 seconds) flatMap { e =>
          e.dataBytes
            .runFold(ByteString.empty) { case (acc, b) => acc ++ b }
            .map(k => parse(k.map(_.toChar).mkString)
            match {
              case Left(failure) => HttpResponse(
                StatusCodes.OK,
                List(),
                HttpEntity("NO RESULTS".map(_.toByte).toArray),
                HttpProtocol("HTTP/1.1")
              )
              case Right(json) => {
                json.hcursor.withFocus{
                  _.mapObject(x =>
                    x.add("extraData",extraData)
                  )
                }.top match {
                  case Some(jsn) => {
                    HttpResponse(
                      StatusCodes.OK,
                      List(headers.`Content-Type`(ContentType(MediaTypes.`application/json`,() => HttpCharsets.`UTF-8`))),
                      HttpEntity(jsn.noSpaces.toCharArray.map(_.toByte)),
                      HttpProtocol("HTTP/1.1")
                    )
                  }
                }
              }}
            )
        }
      }}
    complete(responseFuture)

При преобразовании байтов ответа из Bing я попытался использовать функцию .utf8String, но она испортила Json, поэтому я приступил к анализубайтов с картой. (_ toChar) .mkString.

Если есть лучший способ написания этого кода, было бы неплохо увидеть его.Спасибо.

...