I'm trying to process a server response which is GZIP'd. The response comes with a header
Content-Type: application/x-gzip
but does not have header
Content-Encoding: gzip
If I add that header using a proxy, the response gets parsed just fine.
I don't have any control over the server, so I can't add the header.
Can I force Retrofit to treat it as GZIP content? Is there a better way?
The URL for the server is:
http://crowdtorch.cms.s3.amazonaws.com/4474/Updates/update-1.xml
There is a better way than reinventing the wheel. Just add the Content-Encoding
header yourself.
.addNetworkInterceptor((Interceptor.Chain chain) -> {
Request req = chain.request();
Headers.Builder headersBuilder = req.headers().newBuilder();
String credential = Credentials.basic(...);
headersBuilder.set("Authorization", credential);
Response res = chain.proceed(req.newBuilder().headers(headersBuilder.build()).build());
return res.newBuilder()
.header("Content-Encoding", "gzip")
.header("Content-Type", ""application/json")
.build();
})
In fact, your code is a classic example of the evils of using internal code (like com.sun
packages from the JDK). RealResponseBody
doesn't have that constructor anymore.
I figured it out. The idea is to add a custom interceptor which will take the not-yet-unzipped response, and unzip it 'manually' - do the same thing that OkHttp would do automatically based on Content-Encoding header, but without requiring that header.
is like dis:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new UnzippingInterceptor());
OkHttpClient client = clientBuilder.build();
And the Interceptor is like dis:
private class UnzippingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return unzip(response);
}
}
And the unzip function is like dis:
// copied from okhttp3.internal.http.HttpEngine (because is private)
private Response unzip(final Response response) throws IOException {
if (response.body() == null) {
return response;
}
GzipSource responseBody = new GzipSource(response.body().source());
Headers strippedHeaders = response.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
return response.newBuilder()
.headers(strippedHeaders)
.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)))
.build();
}