Okhttp: How should I handle gzip in okhttp (decompressing)?

Created on 18 Dec 2015  路  6Comments  路  Source: square/okhttp

For my current project I'm currently using OkHttp to connect to an API endpoint. Initially I assumed that it would use gzip automatically in the request, but it doesn't seem to enable it?

Because of this, I added an additional header (.addHeader("Accept-Encoding", "gzip")) to tell the server that I would like a gzip compressed result. After adding this, the response is indeed compressed, however, I am wondering if the okhttp is supposed to handle gzip content automatically (Because the description talks about Transparent GZIP)? For now it seems like I have to manually modify my incoming stream before I can use it in my JSON parser (Using LoganSquare)

Question: Any thoughts on how I could implement this in a better way?

Sample:

OkHttpClient client = new OkHttpClient();

Request request =  new Request.Builder().url("https://api.awesomecompany.com/details/item/1000")
                                                .addHeader("X-TOKEN", "Bearer " + Auth.getInstance(mContext).getToken())
                                                .addHeader("Accept-Encoding", "gzip")
                                                .build();

Response response = client.newCall(request).execute();

if (responseCode == 200) {
    // Regular JSON parsing to model
    ItemDetailsModel itemDetailsModel = LoganSquare.parse(response.body().byteStream(), ItemDetailsModel.class);
    long responseSize = response.body().contentLength();    // Size in bytes
    ... use my model

    // Manually decompress GZIP?
    ItemDetailsModel itemDetailsModel = LoganSquare.parse(new GZIPInputStream(response.body().byteStream()), ItemDetailsModel.class);
    long responseSize = response.body().contentLength();    // Value is -1, how to get the compressed size?
}
needs info

Most helpful comment

Hi @JakeWharton,

thanks for the response. That test certainly works.

I think I misunderstood how "Transparent GZIP" works.

For testing purposes I made a small php script that outputs the value of HTTP_ACCEPT_ENCODING (+ some text to make sure there is enough data to be gzipped). The script would return a gzip version if it was requested, else it would return an uncompressed version. I also made a small Android test project with okhttp that would call this php file.

From what I understand, okhttp will always ask for a gzipped result (testing the php page with curl and the app made this clear). However, unless you've manually added the entry .addHeader("Accept-Encoding", "gzip"), you won't see the value "Content-Encoding: gzip" in the header of the Response object. And if I added it manually, I will have to decode the response.body().byteStream() myself.

Sorry for the confusion, you can close this issue.

All 6 comments

it doesn't seem to enable it?

What makes you say this?

Accept-Encoding: gzip is added automatically and the gzip'd response will be ungzipped transparently. You can confirm by looking for the Transfer-Encoding: gzip header on the networkResponse() on the Response object.

Thanks for the response, I'm using okhttp 2.7.0.

Well, when I look at the response header, I only see this (I removed the .addHeader("Accept-Encoding", "gzip") for testing):

response.networkResponse().headers

Date: Fri, 18 Dec 2015 20:19:13 GMT
X-Powered-By: Express
Access-Control-Allow-Origin: *
access-control-allow-headers: Content-Type, api_key
content-type: application/json; charset=utf-8
content-length: 133
etag: "-518478267"
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
OkHttp-Sent-Millis: 1450469952231
OkHttp-Received-Millis: 1450469952933

This test shows transparent Gzip in action and shows how to verify it. Can you try that? Are you sure your server supports it?

Hi @JakeWharton,

thanks for the response. That test certainly works.

I think I misunderstood how "Transparent GZIP" works.

For testing purposes I made a small php script that outputs the value of HTTP_ACCEPT_ENCODING (+ some text to make sure there is enough data to be gzipped). The script would return a gzip version if it was requested, else it would return an uncompressed version. I also made a small Android test project with okhttp that would call this php file.

From what I understand, okhttp will always ask for a gzipped result (testing the php page with curl and the app made this clear). However, unless you've manually added the entry .addHeader("Accept-Encoding", "gzip"), you won't see the value "Content-Encoding: gzip" in the header of the Response object. And if I added it manually, I will have to decode the response.body().byteStream() myself.

Sorry for the confusion, you can close this issue.

Yep. Your summary of the behavior is correct. Glad it's figured out.

and what would be for

    HTTP/1.1 200 OK
    Date: Tue, 31 Dec 2019 19:03:16 GMT
    Server: Apache
    Upgrade: h2,h2c
    Connection: Upgrade, close
    Last-Modified: Sat, 21 Oct 2017 08:55:53 GMT
    Accept-Ranges: bytes
    Content-Length: 13857268
    Vary: Accept-Encoding,User-Agent
    Content-Type: font/ttf

i tried this

@Headers("Content-Type: font/ttf")
    @GET("fsharpapps/fonts/myfile.ttf")
    @Streaming
    Call<ResponseBody> downloadFile();

but fizesize return -1

Was this page helpful?
0 / 5 - 0 ratings