私達が呼べるエンドポイントがあります /test
サードパーティのAPIから内部的にデータを取得するそして、応答を返す前に何らかの変換を行いたいと考えています。私がハングアップしているのは、このサードパーティのAPIがgzipされたJSONを返しており、(まだ)それをデコードできないことです。 decodeRequestディレクティブ しかし、私は自分のルーティングでこれを使用しなければならないようで、私はここでより深いレベルにいます。を受け取ったときに呼び出す内部メソッドがあります。 GET
私のエンドポイントへ /test
という名前 do3rdPartyAPIRequest
私が構築するところ HttpRequest
そしてに渡る Http().singleRequest()
だからその見返りに私は持っている Future[HttpResponse]
それが私が私がなりたいと思う場所ですが、私はここで立ち往生しています。
いくつかのローカルAPIを使用して、同様の方法で構築および使用したので、応答をエンコードすることはできませんでした。 Future[HttpResponse]
レスポンスのステータスを確認してからJSONに変換します。 Unmarshal
しかし、JSONに変換する前に私が知る限り、これには追加のステップが必要です。私はこの質問は非常によく似ていると思います これです しかしそれはスプレー特有であり、私はこの答えを現在のakka httpに翻訳することができなかった。
回答:
回答№1は6最後にこれを考え出した - これは応答からバイト文字列を取得するための絶対的な最善ではないかもしれませんがそれは動作します..あなたが使用できることがわかった Gzipクラス
そして2つの選択肢があります
Gzip.decode
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については2
あなたは、圧縮されたコンテンツがデフォルトでakka-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]
}
}
})