У мене є кінцева точка, яку ми можемо зателефонувати /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
і у вас є два варіанти
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]
}
}
})