/ / Розшифруйте gzipped JSON в Akka HTTP - json, scala, akka-http

Розшифруйте Gzip JSON в Akka HTTP - json, scala, akka-http

У мене є кінцева точка, яку ми можемо зателефонувати /test що внутрішньо отримує дані зі сторонніх APIа потім хоче зробити певну трансформацію, перш ніж повернути відповідь. Де я зависаю, це сторонній API повертає gzipped JSON, і я не можу його розшифрувати (поки що). Я знайшов директива decodeRequest але, здається, я повинен використовувати це у своєму маршруті, і я тут на глибший рівень. У мене є внутрішній метод, до якого я телефоную, як тільки отримаю GET до моєї кінцевої точки /test який названий do3rdPartyAPIRequest де я будую HttpRequest і перейти до Http().singleRequest() то тоді взамін я маю Future[HttpResponse] де я думаю, що хочу бути, але я застряг тут.

З деякими локальними API, які я будував і споживав подібним чином, я не кодував свої відповіді так типово за допомогою Future[HttpResponse] Я перевіряю стан відповіді та переходжу до JSON через Unmarshal але для цього потрібен додатковий крок, наскільки мені відомо, перед перетворенням на JSON. Я розумію, що це питання дуже схоже на цей однак це специфічно для спрею, і я не зміг перекласти цю відповідь на поточну сторінку akka http

Відповіді:

6 за відповідь № 1

Нарешті зрозумів це - це, можливо, не найкраще отримати байтосерінг із відповіді, але це працює .. Виявляється, ви можете використовувати Клас Gzip

і у вас є два варіанти

  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 для відповіді № 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]
}
}
})