Android: Http Communication Should Use "Accept-Encoding: Gzip"

Android: HTTP communication should use Accept-Encoding: gzip

You should use http headers to indicate a connection can accept gzip encoded data, e.g:

HttpUriRequest request = new HttpGet(url);
request.addHeader("Accept-Encoding", "gzip");
// ...
httpClient.execute(request);

Check response for content encoding:

InputStream instream = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
instream = new GZIPInputStream(instream);
}

http server not honoring Accept-Encoding: gzip unless User-Agent is known browser

It's almost certainly doing this because some legacy User-Agents advertise support for GZIP and then fail to properly decompress the content. For that reason, some server-side frameworks are known to only send compressed responses to clients known not to suffer bugs like that.

What header should be used for sending GZIP compressed JSON from Android Client to Server?

To inform the server that you are sending gzip-encoded data, send the Content-Encoding header, not Accept-Encoding.

Android HttpURLConnection: gzip compression

You dont need to handle this. just use conn.getInputStream()

From this blogpost:

In Gingerbread, we added transparent response compression. HttpURLConnection will automatically add this header to outgoing requests, and handle the corresponding response:

Accept-Encoding: gzip

Retrofit and OkHttp gzip decode

Replace this:

@Headers({
"Accept-Encoding: gzip, deflate",
"Content-Type: application/json;charset=utf-8",
"Accept: application/json"
})

With this:

@Headers({
"Content-Type: application/json;charset=utf-8",
"Accept: application/json"
})

When you provide your own Accept-Encoding header you’re instructing OkHttp that you want to do your own decompression. By omitting it, OkHttp will take care of both adding the header and the decompression.

okhttp 3: how to decompress gzip/deflate response manually using Java/Android

After 6 hours of digging I found the correct solution and as usual it was easier than I thought, so I was basically trying to decompress a page that's not gzipped for that reason it was failing. Now once I hit the second page (which is compressed) I get a gzipped response where the code above should handle it. Also if anyone wants the solution I used a modified interceptor just like the one in this answer so you don't need to use a custom function to handle the decompression.

I modified the unzip method to make the okhttp interceptor work with compressed and uncompressed responses:

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);
}


// copied from okhttp3.internal.http.HttpEngine (because is private)
private Response unzip(final Response response) throws IOException {
if (response.body() == null)
{
return response;
}

//check if we have gzip response
String contentEncoding = response.headers().get("Content-Encoding");

//this is used to decompress gzipped responses
if (contentEncoding != null && contentEncoding.equals("gzip"))
{
Long contentLength = response.body().contentLength();
GzipSource responseBody = new GzipSource(response.body().source());
Headers strippedHeaders = response.headers().newBuilder().build();
return response.newBuilder().headers(strippedHeaders)
.body(new RealResponseBody(response.body().contentType().toString(), contentLength, Okio.buffer(responseBody)))
.build();
}
else
{
return response;
}
}
}

Handling gzipped content on Android

You can wrap the result of url.openStream() in a GZIPInputStream. eg:

InputSource is = new InputSource(new GZIPInputStream(url.openStream()));

To auto-detect when to do this, use the Content-Encoding HTTP header. eg:

URLConnection connection = url.openConnection();
InputStream stream = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
stream = new GZIPInputStream(stream));
}
InputSource is = new InputSource(stream);


Related Topics



Leave a reply



Submit