Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpURLConnection not decompressing Gzip

I'm trying to use HttpURLConnection on Gingerbread+ Android devices and am having trouble with the gzip encoding. According to the documentation

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

Accept-Encoding: gzip"

The problem is that this is not actually happening. The Accept-Encoding: gzip header is not getting added at all. If I add it manually, I would then expect the decompressing part of it to work by connection.openInputStream() to automatically return a GZipInputStream but it just returns a plain InputStream.

Has anyone experienced this? I havent seen any posts of this happening so its very odd. The project is compiled against API 17 so that shouldnt be a problem and the device is running 4.3.

Thanks.

like image 202
Kyle Fowler Avatar asked Sep 19 '13 15:09

Kyle Fowler


4 Answers

I had the same problem and it was related to HTTPS. If you call:

URL url = new URL("https://www.example.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

you actually get an instance of HttpsURLConnection (a subclass of HttpURLConnection) that does NOT handle gzip automatically. In those cases you can:

conn.setRequestProperty("Accept-Encoding", "gzip");
...
InputStream inStream = new GZIPInputStream(conn.getInputStream());
like image 51
idrosid Avatar answered Nov 09 '22 13:11

idrosid


Since Android Gingerbread (http) and ICS (http + https), when you use Http(s)URLConnection, Android adds the Accept-Encoding: gzip header automatically, but only if you didn't add it yourself first.

In that case, if the server returns gzip-encoded content, you will automatically get a GZIPInputStream and the Content-Encoding: gzip header will be removed from the response. That's why it's called transparent: so the client cannot tell the difference between compressed or uncompressed responses by looking at the stream content or the headers.

If you add the Accept-Encoding: gzip header manually yourself however, then transparent gzip handling is disabled for that request and if the server returns gzip-compressed content, then you need to look for the Content-Encoding: gzip header and create the GZIPInputStream yourself to decompress content.

like image 21
BladeCoder Avatar answered Nov 09 '22 12:11

BladeCoder


I tested with a few of my devices and HttpURLConnection is adding Accept-Encoding: gzip to the headers.

Have you tried configuring Fiddler for your Android devices to verify http headers? Perhaps your server does not support compression.

like image 2
Andy Gaskell Avatar answered Nov 09 '22 13:11

Andy Gaskell


I've experienced this myself and also found that it worked if I added the header and used GZIPInputStream manually. However, we were setting our headers manually (had a custom header we had to add).

The Android documentation says "By default, this implementation of HttpURLConnection requests that servers use gzip compression." So I'm guessing that the default only applies if you don't manually set the headers.

like image 2
Swampie Avatar answered Nov 09 '22 13:11

Swampie