Akka Http。转换API响应并转发它

时间:2018-05-29 11:53:04

标签: scala akka-http

我有一个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 :(得分:0)

我最终使用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。

如果有更好的方法来编写此代码,那么很高兴看到它。感谢。