Quantcast
Channel: okhttp 3: how to decompress gzip/deflate response manually using Java/Android - Stack Overflow
Viewing all articles
Browse latest Browse all 6

Answer by Richard Maw for okhttp 3: how to decompress gzip/deflate response manually using Java/Android

$
0
0

I had to implement this myself recently and found that existing answers had a few errors, so here's my take with how it works today.

import java.util.Collections;import java.util.zip.Inflater;import okhttp3.Headers;import okhttp3.Interceptor;import okhttp3.MediaType;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;import okhttp3.ResponseBody;import okio.BufferedSource;import okio.GzipSource;import okio.InflaterSource;import okio.Okio;var client = new OkHttpClient.Builder()    .addInterceptor(        (Interceptor.Chain chain) -> {          var oldRequest = chain.request();          // If the caller has passed their own Accept-Encoding          // it's indicating they expect to handle it themself.          if (oldRequest.header("Accept-Encoding") != null) {            return chain.proceed(oldRequest);          }          // Augment request saying we accept multiple content encodings          var newHeaders =              oldRequest                  .headers()                  .newBuilder()                  .add("Accept-Encoding", "deflate")                  .add("Accept-Encoding", "gzip")                  .build();          var newRequest = oldRequest.newBuilder().headers(newHeaders).build();          var oldResponse = chain.proceed(newRequest);          // Replace the response's request with the original one          var responseBuilder = oldResponse.newBuilder().request(oldRequest);          // We might not have a body to decompress          var body = oldResponse.body();          if (body != null) {            BufferedSource source = body.source();            // The body may have been wrapped in an arbitrary encoding sequence            // and the server returns them in the order it encoded them            // so we wrap them with decoders in reverse order.            var encodings = oldResponse.headers().values("Content-Encoding");            Collections.reverse(encodings);            for (var encoding : encodings) {              if ("deflate".equalsIgnoreCase(encoding)) {                var inflater = new Inflater(true);                source = Okio.buffer(new InflaterSource(source, inflater));              } else if ("gzip".equalsIgnoreCase(encoding)) {                source = Okio.buffer(new GzipSource(source));              }            }            // Strip encoding and length headers as we've already handled them            var strippedHeaders =                oldResponse                    .headers()                    .newBuilder()                    .removeAll("Content-Encoding")                    .removeAll("Content-Length")                    .build();            responseBuilder.headers(strippedHeaders);            var contentType = MediaType.parse(oldResponse.header("Content-Type"));            // Construct a new body with an inferred Content-Length            var newBody = ResponseBody.create(contentType, -1L, source);            responseBuilder.body(newBody);          }          return responseBuilder.build();        })    .build();

Viewing all articles
Browse latest Browse all 6

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>