Decode gzipped JSON in Akka HTTP
Finally figured this out - this might not be the absolute best to get a bytestring from response but it works .. Turns out you can use Gzip class
and you have two options
Gzip.decode
Gzip.decoderFlow
Here are my examples in case this helps you:
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])}
You would expect that compressed content would be managed by akka-http by default, but it only provides PredefinedFromEntityUnmarshallers
and inside entity there is not information about Content-encoding
header.
To solve this you have to implement your own Unmarshaller and to have it in scope
Example:
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] } } })