2016-08-17 50 views
1

我有一個端點,我們可以調用/test從內部獲取來自第三方API的數據,然後在返回響應之前想要做一些轉換。我掛斷了這個第三方API返回gzip的JSON,我無法解碼它(還)。我發現decodeRequest directive,但似乎我必須在我的路由中使用它,而且我在這裏的層次更深。我有一個內部方法,我稱之爲一次我收到一個GET我的終點/test,我建立一個HttpRequest,並傳遞給Http().singleRequest()所以後來在回我有一個Future[HttpResponse]這是我想,我想,但我是被命名爲do3rdPartyAPIRequest卡在這裏。在Akka中解碼gzip的JSON HTTP

隨着一些地方的API我建,並以類似的方式我沒有我的編碼,這樣的反應通常與Future[HttpResponse]我檢查響應狀態,並通過Unmarshal進入轉換成JSON消耗,但這需要一個額外的步驟遠正如我在轉換爲JSON之前所知道的那樣。我意識到這個問題是非常相似的this one然而,這是噴霧具體的,我還沒有能夠將此答案轉換成當前akka http

回答

6

最後解決這個問題 - 這可能不是絕對最好的從一個字符串反應,但它的工作原理..原來你可以使用Gzip class

,你有兩個選擇

  1. Gzip.decode
  2. Gzip.decoderFlow

這裏是我的案例這可以幫助你:

def getMyDomainObject(resp: HttpResponse):Future[MyDomain] = { 
for { 
    byteString <- resp.entity.dataBytes.runFold(ByteString(""))(_ ++ _) 
    decompressedBytes <- Gzip.decode(byteString) 
    result <- Unmarshal(decompressedBytes).to[MyDomain] 
    } yield result 
} 


def getMyDomainObjectVersion2(resp:HttpResponse):Future[MyDomain] = { 
    resp.entity.dataBytes 
    .via(Gzip.decoderFlow) 
    .runWith(Sink.head) 
    .flatMap(Unmarshal(_).to[MyDomain]) 
} 
2

你會認爲壓縮的內容會被阿卡-HTTP默認可管理的,但它僅提供PredefinedFromEntityUnmarshallers和內實體沒有相關信息Content-encoding標題。

爲了解決這個問題,你必須實現自己的Unmarshaller,並把它的範圍

例子:

implicit val gzipMessageUnmarshaller = Unmarshaller(ec => { 
     (msg: HttpMessage) => { 
     val `content-encoding` = msg.getHeader("Content-Encoding") 
     if (`content-encoding`.isPresent && `content-encoding`.get().value() == "gzip") { 
      val decompressedResponse = msg.entity.transformDataBytes(Gzip.decoderFlow) 
      Unmarshal(decompressedResponse).to[String] 
     } else { 
      Unmarshal(msg).to[String] 
     } 
     } 
    })