110

I've a HTTP communication to a webserver requesting JSON data. I'd like compress this data stream with Content-Encoding: gzip. Is there a way I can set Accept-Encoding: gzip in my HttpClient? The search for gzip in the Android References doesn't show up anything related to HTTP, as you can see here.

znq
  • 44,613
  • 41
  • 116
  • 144
  • 1
    [Android-WebRequest](https://github.com/delight-im/Android-WebRequest) supports GZIP and uncompressed responses automatically, e.g. with `new WebRequest().get().to("http://www.example.com/").askForGzip(true).executeSync()`. Specifically, the method [parseResponse(...)](https://github.com/delight-im/Android-WebRequest/blob/master/src/im/delight/android/webrequest/WebRequest.java) should be what you're looking for. – caw Jun 30 '14 at 16:47

5 Answers5

175

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);
}
Bakhtiyor
  • 4,356
  • 2
  • 23
  • 15
  • 7
    That is a great and very helpful answer with all the details I needed. Thanks a lot. One comment: instead of addHeader I used setHeader. From what I understand this overwrites the existing "Accept-Encoding" if there is one. Not sure which approach is the right/better one. To overwrite an existing header to make sure it has the right value, or to add it in case that there can be other Accept-Encoding headers in parallel. – znq Oct 16 '09 at 08:04
  • where do you put the instream then? – Mikey Dec 07 '10 at 10:18
  • 7
    this does not gzip the request, it only tells the server that you can accept a gzip'd response. – Jeffrey Blattman May 04 '11 at 17:47
  • 1
    For anyone also having trouble to get this up and running for google services here are two issues which took me quite some time to find out: (1) some google services require the user agent string provided by the client to contain the string `gzip` to _really_ enable gzip compression. (2) keep in mind that the server may not gzip the response if it is too small... – sven Jun 17 '11 at 07:30
  • My problem is that the gzip header is nowhere to be seen. I am using Wireshark to sniff the network on the server side, and I see no trace of the "gzip" header that I added in android... – Ted Feb 16 '14 at 14:21
  • @znq Android itself uses `addHeader(...)` in `AndroidHttpClient`'s method `modifyRequestToAcceptGzipResponse(...)` so you should probably use that. – caw Jun 30 '14 at 15:30
33

If you're using API level 8 or above there's AndroidHttpClient.

It has helper methods like:

public static InputStream getUngzippedContent (HttpEntity entity)

and

public static void modifyRequestToAcceptGzipResponse (HttpRequest request)

leading to much more succinct code:

AndroidHttpClient.modifyRequestToAcceptGzipResponse( request );
HttpResponse response = client.execute( request );
InputStream inputStream = AndroidHttpClient.getUngzippedContent( response.getEntity() );
Volker Neumann
  • 476
  • 5
  • 6
13

I think the sample of code at this link is more interesting: ClientGZipContentCompression.java

They are using HttpRequestInterceptor and HttpResponseInterceptor

Sample for request:

        httpclient.addRequestInterceptor(new HttpRequestInterceptor() {

            public void process(
                    final HttpRequest request,
                    final HttpContext context) throws HttpException, IOException {
                if (!request.containsHeader("Accept-Encoding")) {
                    request.addHeader("Accept-Encoding", "gzip");
                }
            }

        });

Sample for answer:

        httpclient.addResponseInterceptor(new HttpResponseInterceptor() {

            public void process(
                    final HttpResponse response,
                    final HttpContext context) throws HttpException, IOException {
                HttpEntity entity = response.getEntity();
                Header ceheader = entity.getContentEncoding();
                if (ceheader != null) {
                    HeaderElement[] codecs = ceheader.getElements();
                    for (int i = 0; i < codecs.length; i++) {
                        if (codecs[i].getName().equalsIgnoreCase("gzip")) {
                            response.setEntity(
                                    new GzipDecompressingEntity(response.getEntity()));
                            return;
                        }
                    }
                }
            }

        });
Niqo
  • 1,072
  • 10
  • 20
  • 1
    Any reason why you think it is more interesting? – Gaurav Agarwal Jul 10 '12 at 16:58
  • 3
    @codingcrow Here's what you're looking for : _In this particular case HTTP client is made capable of transparent content GZIP compression by adding two protocol interceptors: a request interceptor that adds 'Accept-Encoding: gzip' header to all outgoing requests and a response interceptor that automatically expands compressed response entities by wrapping them with a uncompressing decorator class. The use of protocol interceptors makes content compression completely transparent to the consumer of the HttpClient interface._ – clauziere Dec 03 '12 at 21:16
  • [Source](http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientGZipContentCompression.java) – clauziere Dec 03 '12 at 21:16
  • GzipDecompressingEntity can't be found in android.jar (2.2) – imcaptor Apr 08 '13 at 05:32
1

I haven't used GZip, but I would assume that you should use the input stream from your HttpURLConnection or HttpResponse as GZIPInputStream, and not some specific other class.

Dimitar Dimitrov
  • 16,032
  • 5
  • 53
  • 55
  • HTTPURLConnection has gzip turned on by default. You just need to make sure your web server can return gzip pages. http://developer.android.com/reference/java/net/HttpURLConnection.html I was able to return gzip pages from php by using ob_start("ob_gzhandler"); – metric152 Aug 13 '12 at 18:35
  • Don't answer when you don't have an answer! – Martin.Martinsson Mar 27 '18 at 03:11
0

In my case it was like this:

URLConnection conn = ...;
InputStream instream = conn.getInputStream();
String encodingHeader = conn.getHeaderField("Content-Encoding");
if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip"))
{
    instream = new GZIPInputStream(instream);
}
kospol
  • 377
  • 3
  • 9