Получение "источника исчерпан преждевременно" при раздутии gzip тела ответа HTTP

Я получаю следующую ошибку при попытке сделать HTTP-вызов с помощью okhttp:

W/System.err: java.io.EOFException: source exhausted prematurely
W/System.err:     at okio.InflaterSource.read(InflaterSource.java:83)
W/System.err:     at okio.GzipSource.read(GzipSource.java:80)
W/System.err:     at okio.Buffer.writeAll(Buffer.java:1135)
W/System.err:     at okio.RealBufferedSource.readString(RealBufferedSource.java:199)
W/System.err:     at okhttp3.ResponseBody.string(ResponseBody.java:176)
W/System.err:     at com.ethanwang.andplay.OKHttpTaskTag.doInBackground(OKHttpTaskTag.java:41)
W/System.err:     at com.ethanwang.andplay.OKHttpTaskTag.doInBackground(OKHttpTaskTag.java:20)
W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:295)
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
W/System.err:     at java.lang.Thread.run(Thread.java:818)

Мне удалось найти только эту проблему: https://github.com/square/okhttp/issues/2193 но я убедился, что Content-Length правильная длина тела ответа. Вот мой логированный запрос и ответ охтпп:

Запрос:

    I/System.out: INFO: Sending request http://test.essaybot.com/msg/tag_search on Connection{test.essaybot.com:80, proxy=DIRECT@ hostAddress=test.essaybot.com/34.208.145.50:80 cipherSuite=none protocol=http/1.1}
I/System.out: Content-Type: application/x-www-form-urlencoded
I/System.out: Content-Length: 33
I/System.out: Host: test.essaybot.com
I/System.out: Connection: Keep-Alive
I/System.out: Accept-Encoding: gzip
I/System.out: User-Agent: okhttp/3.11.0

Отклик:

I/System.out: INFO: Received response for http://test.essaybot.com/msg/tag_search in 62.2ms
I/System.out: Cache-Control: no-cache
I/System.out: Content-Encoding: gzip
I/System.out: Content-Length: 139
I/System.out: Content-Type: application/json
I/System.out: Set-Cookie: PHP_SESSION=0Q4rZJplDjrUNB4ZbWAG; Path=/; Max-Age=2592000
I/System.out: Set-Cookie: VISITOR_ID=65xGr53M1xM0waK8; Path=/; Max-Age=31536000
I/System.out: Date: Wed, 29 Aug 2018 20:45:06 GMT
I/System.out: INFO: Received response body bytes: 
I/System.out:  [31, -117, 8, 0, 0, 0, 0, 0, 0, -1, 44, -51, 65, 10, -62, 64, 12, 5, -48, -85, 72, -42, 93, -72, -18, -50, -91, 103, 16, -111, -23, 52, -83, 31, 66, -90, 100, 50, -94, -120, 119, -105, 116, -70, 9, 47, -16, -109, -1, 37, 54, 123, 104, -95, -15, 60, -112, 113, 109, -30, 52, -34, -24, 50, -65, 88, -67, 25, -45, 16, 70, -34, 97, 30, 115, 49, -28, 20, -128, 9, -108, 107, 80, -33, 96, -1, -12, 12, 22, 100, 36, 57, 93, -43, 89, 4, 43, 107, -65, -34, -74, 61, 58, -49, -56, -114, -94, -31, 86, -35, -110, -32, -8, 54, -23, 20, 88, -95, 107, -81, 101, 115, -44, 99, -109, 92, -98, 69, 66, 21, -119, -18, -65, 63, 0, 0, 0, -1, -1] 
I/System.out:  With length: 139

Сервер отлично работает с нашим вебом и iOS заканчивается. Он также работал нормально с Android до примерно двух месяцев назад, когда он вдруг перестал работать без изменений в сети. Что еще может вызвать эту ошибку?

-------------------------------------- обновлено ----------- ---------------------------

Кажется, что данные в буфере читабельны, так как из отладчика выше читаемый текст ([size=185 text={"err_no":0,"result":["Adventure","Advice","Art","Africa","Airli…]) аннотируется после буферной переменной. Кроме того, данные отладчика отличаются от зарегистрированных данных:

data = {byte[8192]@4418} 
 0 = 123
 1 = 34
 2 = 101
 3 = 114
 4 = 114
 5 = 95
 6 = 110
 7 = 111
 8 = 34
 9 = 58
 10 = 48
 11 = 44
 12 = 34
 13 = 114
 14 = 101
 15 = 115
 16 = 117
 17 = 108
 18 = 116
 19 = 34
 20 = 58
 21 = 91
 22 = 34
 23 = 65
 24 = 100
 25 = 118
 26 = 101
 27 = 110
 28 = 116
 29 = 117
 30 = 114
 31 = 101
 32 = 34
 33 = 44
 34 = 34
 35 = 65
 36 = 100
 37 = 118
 38 = 105
 39 = 99
 40 = 101
 41 = 34
 42 = 44
 43 = 34
 44 = 65
 45 = 114
 46 = 116
 47 = 34
 48 = 44
 49 = 34
 50 = 65
 51 = 102
 52 = 114
 53 = 105
 54 = 99
 55 = 97
 56 = 34
 57 = 44
 58 = 34
 59 = 65
 60 = 105
 61 = 114
 62 = 108
 63 = 105
 64 = 110
 65 = 101
 66 = 115
 67 = 34
 68 = 44
 69 = 34
 70 = 65
 71 = 110
 72 = 120
 73 = 105
 74 = 101
 75 = 116
 76 = 121
 77 = 34
 78 = 44
 79 = 34
 80 = 65
 81 = 114
 82 = 116
 83 = 105
 84 = 102
 85 = 105
 86 = 99
 87 = 105
 88 = 97
 89 = 108
 90 = 32
 91 = 73
 92 = 110
 93 = 116
 94 = 101
 95 = 108
 96 = 108
 97 = 105
 98 = 103
 99 = 101
 100 = 110
 101 = 99
 102 = 101
 103 = 34
 104 = 44
 105 = 34
 106 = 65
 107 = 112
 108 = 112
 109 = 115
 110 = 34
 111 = 44
 112 = 34
 113 = 65
 114 = 100
 115 = 100
 116 = 105
 117 = 99
 118 = 116
 119 = 105
 120 = 111
 121 = 110
 122 = 34
 123 = 44
 124 = 34
 125 = 65
 126 = 117
 127 = 115
 128 = 116
 129 = 114
 130 = 97
 131 = 108
 132 = 105
 133 = 97
 134 = 34
 135 = 44
 136 = 34
 137 = 65
 138 = 105
 139 = 114
 140 = 98
 141 = 110
 142 = 98
 143 = 34
 144 = 44
 145 = 34
 146 = 65
 147 = 103
 148 = 105
 149 = 110
 150 = 103
 151 = 34
 152 = 44
 153 = 34
 154 = 65
 155 = 100
 156 = 118
 157 = 101
 158 = 114
 159 = 116
 160 = 105
 161 = 115
 162 = 105
 163 = 110
 164 = 103
 165 = 34
 166 = 44
 167 = 34
 168 = 65
 169 = 108
 170 = 99
 171 = 111
 172 = 104
 173 = 111
 174 = 108
 175 = 34
 176 = 44
 177 = 34
 178 = 65
 179 = 115
 180 = 105
 181 = 97
 182 = 34
 183 = 93
 184 = 125
 185 = 0
 186 = 0
 187 = 0
 188 = 0
 189 = 0
 190 = 0
 191 = 0
 192 = 0
 193 = 0
 194 = 0
 195 = 0
 196 = 0
 197 = 0
 198 = 0
 199 = 0 

----------------------- Обновить ------------------------

Я использовал отладчик, чтобы отследить проблему, и похоже, что gzipped ответ был распакован дважды. Как показано на рисунках, read в InflaterSource.java вызывается дважды. Исключение выдается во второй раз, когда он распаковывается.

Первый раз <code>read</code> называется</p><p> <a href=Второй раз <code>read</code> называется, исключение брошено</p>
                                    
                                
                            </div>
                        </div>
                    </div>
                    <div class=

2 ответа

У меня была эта ошибка при запросе модификации GET на случайном сайте, я добавил

 @Headers("Accept-Encoding: identity")

починить это.

identity Указывает функцию идентичности (т. е. отсутствие сжатия или модификации). Это значение всегда считается приемлемым, даже если оно отсутствует.

Данные сервера повреждены. Он должен содержать трейлер GZIP, чтобы указать конец потока, и это отсутствует.

Вы можете использовать этот код для получения входного потока. Я надеюсь, что это сработает для вас.

private static String getResponseString(Response response) {
    try {
        InputStream inputStream;
        String contentEncodingHeader = response.header("Content-Encoding");
        if (contentEncodingHeader != null && contentEncodingHeader.equals("gzip")) {
            // Read the zipped contents.
            inputStream = new GZIPInputStream(response.body().byteStream());
        } else {
            // Read the normal contents.
            inputStream = response.body().byteStream();
        }

        // Create and return buffered reader.
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        // Read stream.
        StringBuilder sb = new StringBuilder("");
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line.trim());
        }
        // Close everything.
        response.body().close();
        inputStream.close();
        br.close();
        return sb.toString();
    } catch (IOException e) {
        return "";
    }
}
Другие вопросы по тегам