Модернизация и декодирование OkHttp gzip

Служба REST, которую я хочу использовать, представляет собой JSON, закодированный с помощью gzip. Он предоставляет Content-Encoding: gzip, но мой OkHttp не кодирует его в читаемый текст, поэтому преобразователь JSON выдает исключение.

---> HTTP GET https://rapla.dhbw-karlsruhe.de/rapla/events?resources=%5B%27rc85dbd6-7d98-4eb7-a7f6-b867213c73d8%27%5D&start=2015-09-01&end=2015-12-31
Accept-Encoding: gzip, deflate
Accept: application/json
Authorization: *not posted*
Content-Type: application/json;charset=utf-8
---> END HTTP (no body)
<--- HTTP 200 https://rapla.dhbw-karlsruhe.de/rapla/events?resources=%5B%27rc85dbd6-7d98-4eb7-a7f6-b867213c73d8%27%5D&start=2015-09-01&end=2015-12-31 (13ms)
Date: Tue, 24 Nov 2015 09:09:10 GMT
Server: Jetty(9.2.2.v20140723)
Expires: Tue, 01 Jan 1980 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache, must-revalidate
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Content-Disposition: attachment
Content-Length: 9684
Via: 1.1 rapla.dhbw-karlsruhe.de
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1448356149978
OkHttp-Received-Millis: 1448356149991

����WK�{��J�`k�_��Z����E�p�>3m�WMa�ג�ҵ�p�0��<��
... skipped rest of the body
E��>���S���n 
<--- END HTTP (9684-byte body)

Согласно комментарию Jake Whartons, заголовок Content-Encoding: gzip должен указать OkHttp декодировать тело.

Код для создания RestAdapter:

final RestAdapter adapter = new RestAdapter.Builder()
    .setEndpoint(baseUrl)
    .setClient(new OkClient(new OkHttpClient()))
    .setConverter(new GsonConverter(gson))
    .setLogLevel(RestAdapter.LogLevel.FULL)
    .build();
service = adapter.create(RaplaService.class);

Зависимости градации:

compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.6.0'

Метод в моем ServiceInterface:

@Headers({
        "Accept-Encoding: gzip, deflate",
        "Content-Type: application/json;charset=utf-8",
        "Accept: application/json"
})
@GET("/events")
List<Event> getEvents(@Header("Authorization") String token, @Query("resources") String resources, @Query("start") String start, @Query("end") String end);

person Simon Tenbeitel    schedule 24.11.2015    source источник
comment
И как вы извлекаете данные ответа? Вероятно, вы используете неправильный метод.   -  person Antoniossss    schedule 24.11.2015
comment
Я добавил метод GET в свой ServiceInterface. Когда я выполняю тот же запрос с помощью Advanced Rest Client, все работает нормально.   -  person Simon Tenbeitel    schedule 24.11.2015


Ответы (1)


Замените это:

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

С этим:

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

Когда вы предоставляете свой собственный заголовок Accept-Encoding, вы указываете OkHttp, что хотите выполнить распаковку самостоятельно. Опустив его, OkHttp позаботится как о добавлении заголовка, так и о распаковке.

person Jesse Wilson    schedule 24.11.2015
comment
Но получу ли я сжатый ответ, если пропущу "Accept-Encoding: gzip, deflate",? - person Hakim; 20.04.2016
comment
Да. Если вы опустите заголовок Accept-Encoding, OkHttp автоматически добавит свой собственный и распаковает от вашего имени. - person Jesse Wilson; 21.04.2016
comment
Я только что столкнулся с подобной проблемой на Retrofit 2. Но в моем случае я добавил .header("Accept-Encoding", "gzip, deflate") в построитель запросов. - person chubao; 22.06.2016
comment
Добавляйте заголовок Accept-Encoding только в том случае, если вы хотите отключить функцию автоматического gzip в OkHttp. - person Jesse Wilson; 22.06.2016
comment
@DavidCheung Мне не нужно было это добавлять. Согласно Джесси Уилсону, похоже, что OkHttp автоматически добавляет этот заголовок, и если сервер возвращает поток данных gzip, он достаточно умен, чтобы знать это и распаковывать его. Если сервер не отвечает на запрос gzip в заголовке, он не пытается его распаковать. Умный. - person Joshua Pinter; 20.02.2018
comment
@JesseWilson У меня возникла проблема с использованием Gzip с восстановлением. stackoverflow.com/questions/52661900/ Скажите, пожалуйста, где я делаю неправильно? - person Aman Srivastava; 08.10.2018
comment
Удаление Accept-Encoding из @Headers на самом деле не удаляет его — OkHttp по-прежнему добавляет его с помощью gzip, deflate, br. Я не уверен, как удалить его полностью. - person alekop; 03.12.2020
comment
Либо добавьте Accept-Encoding: identity, либо используйте сетевой перехватчик для удаления заголовка исходящего запроса. - person Jesse Wilson; 05.12.2020
comment
в моем случае сервер отправляет мне gzip только в том случае, если я отправляю Accept-Encoding из запроса. - person Erlang Parasu; 05.01.2021