Encoding / Decoding
The HTTP spec defines a Content-Encoding
header, which signifies whether the entity body of an HTTP message is “encoded” and, if so, by which algorithm. The only commonly used content encodings are compression algorithms.
Currently, Akka HTTP supports the compression and decompression of HTTP requests and responses with the gzip
or deflate
encodings. The core logic for this lives in the akka.http.scaladsl.coding
package.akka.http.javadsl.coding.Coder
enum class.
Server side
The support is not enabled automatically, but must be explicitly requested. For enabling message encoding/decoding with Routing DSL see the CodingDirectives.
Client side
There is currently no high-level or automatic support for decoding responses on the client-side.
The following example shows how to decode responses manually based on the Content-Encoding
header:
- Scala
-
source
import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.coding.{ Gzip, Deflate, NoCoding } import akka.http.scaladsl.model._, headers.HttpEncodings import akka.stream.ActorMaterializer import scala.concurrent.Future implicit val system = ActorSystem() implicit val materializer = ActorMaterializer() import system.dispatcher val http = Http() val requests: Seq[HttpRequest] = Seq( "https://httpbin.org/gzip", // Content-Encoding: gzip in response "https://httpbin.org/deflate", // Content-Encoding: deflate in response "https://httpbin.org/get" // no Content-Encoding in response ).map(uri => HttpRequest(uri = uri)) def decodeResponse(response: HttpResponse): HttpResponse = { val decoder = response.encoding match { case HttpEncodings.gzip => Gzip case HttpEncodings.deflate => Deflate case HttpEncodings.identity => NoCoding } decoder.decodeMessage(response) } val futureResponses: Future[Seq[HttpResponse]] = Future.traverse(requests)(http.singleRequest(_).map(decodeResponse)) futureResponses.futureValue.foreach { resp => system.log.info(s"response is ${resp.toStrict(1.second).futureValue}") } system.terminate()
- Java
-
source
import akka.actor.ActorSystem; import akka.http.javadsl.Http; import akka.http.javadsl.coding.Coder; import akka.http.javadsl.model.HttpRequest; import akka.http.javadsl.model.HttpResponse; import akka.http.scaladsl.model.headers.HttpEncodings; import akka.stream.ActorMaterializer; import akka.stream.Materializer; import scala.concurrent.duration.FiniteDuration; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; public class HttpClientDecodingExampleTest { public static void main(String[] args) throws Exception { final ActorSystem system = ActorSystem.create(); final Materializer materializer = ActorMaterializer.create(system); final List<HttpRequest> httpRequests = Arrays.asList( HttpRequest.create("https://httpbin.org/gzip"), // Content-Encoding: gzip in response HttpRequest.create("https://httpbin.org/deflate"), // Content-Encoding: deflate in response HttpRequest.create("https://httpbin.org/get") // no Content-Encoding in response ); final Http http = Http.get(system); final Function<HttpResponse, HttpResponse> decodeResponse = response -> { // Pick the right coder final Coder coder; if (HttpEncodings.gzip().equals(response.encoding())) { coder = Coder.Gzip; } else if (HttpEncodings.deflate().equals(response.encoding())) { coder = Coder.Deflate; } else { coder = Coder.NoCoding; } // Decode the entity return coder.decodeMessage(response); }; List<CompletableFuture<HttpResponse>> futureResponses = httpRequests.stream() .map(req -> http.singleRequest(req, materializer) .thenApply(decodeResponse)) .map(CompletionStage::toCompletableFuture) .collect(Collectors.toList()); for (CompletableFuture<HttpResponse> futureResponse : futureResponses) { final HttpResponse httpResponse = futureResponse.get(); system.log().info("response is: " + httpResponse.entity() .toStrict(1000, materializer) .toCompletableFuture() .get()); } system.terminate(); } }