Skip to content

Commit d894576

Browse files
committed
fix resource not closed in android decompressinterceptor ; fix deflate in android decompressinterceptor (rfc 1950 vs 1951)
1 parent 0193d2c commit d894576

File tree

3 files changed

+39
-18
lines changed

3 files changed

+39
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## 2.3.0
22
- add brotli
33
- set response version on android
4+
- fix resource not closed in android decompressinterceptor
5+
- fix deflate in android decompressinterceptor (rfc 1950 vs 1951)
46
- build : add readme to nuspec
57
- Square.OkHttp3 4.12.0.1
68
- Square.OkHttp3.UrlConnection 4.12.0.1
Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
package securehttpclient.okhttp;
22

3+
import java.io.EOFException;
34
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.io.BufferedInputStream;
47
import java.util.zip.Inflater;
8+
import java.util.zip.InflaterInputStream;
9+
import java.util.zip.GZIPInputStream;
10+
import org.brotli.dec.BrotliInputStream;
511

612
import okhttp3.Headers;
713
import okhttp3.Interceptor;
8-
import okhttp3.Request;
914
import okhttp3.Response;
1015
import okhttp3.ResponseBody;
11-
import okio.GzipSource;
12-
import okio.InflaterSource;
13-
import okio.Source;
16+
import okio.BufferedSource;
1417
import okio.Okio;
1518

16-
import org.brotli.dec.BrotliInputStream;
17-
1819
public class DecompressInterceptor implements Interceptor {
1920
@Override
2021
public Response intercept(Chain chain) throws IOException {
@@ -33,25 +34,44 @@ private Response decompress(final Response response) throws IOException {
3334
return response;
3435
}
3536

36-
Source source = null;
37+
BufferedSource source = response.body().source();
38+
InputStream inputStream = null;
39+
3740
switch(response.header("Content-Encoding").toLowerCase()) {
3841
case "gzip": {
39-
source = new GzipSource(response.body().source());
42+
inputStream = new GZIPInputStream(source.inputStream());
4043
break;
4144
}
4245
case "deflate": {
43-
source = new InflaterSource(response.body().source(), new Inflater());
46+
boolean hasZlibHeader = false;
47+
BufferedInputStream bufferedInputStream = new BufferedInputStream(source.inputStream());
48+
try {
49+
source.require(2); // throws EOFException if size < 2
50+
byte[] headerBytes = new byte[2];
51+
bufferedInputStream.mark(0);
52+
bufferedInputStream.read(headerBytes);
53+
bufferedInputStream.reset();
54+
hasZlibHeader = (headerBytes[0] & 0xFF) == 0x78 && (headerBytes[1] & 0xFF) <= 0xDA;
55+
} catch (EOFException e) {
56+
}
57+
if (hasZlibHeader) {
58+
// zlib decompression (rfc 1951)
59+
inputStream = new InflaterInputStream(bufferedInputStream, new Inflater());
60+
} else {
61+
// raw deflate decompression (rfc 1950)
62+
inputStream = new InflaterInputStream(bufferedInputStream, new Inflater(true));
63+
}
4464
break;
4565
}
4666
case "br": {
47-
source = Okio.source(new BrotliInputStream(response.body().source().inputStream()));
67+
inputStream = new BrotliInputStream(source.inputStream());
4868
break;
4969
}
5070
}
5171

52-
String bodyString = Okio.buffer(source).readUtf8();
53-
54-
ResponseBody responseBody = ResponseBody.create(bodyString, response.body().contentType());
72+
byte[] bodyBytes = Okio.buffer(Okio.source(inputStream)).readByteArray();
73+
ResponseBody responseBody = ResponseBody.create(bodyBytes, response.body().contentType());
74+
inputStream.close();
5575

5676
Headers strippedHeaders = response.headers().newBuilder()
5777
.removeAll("Content-Encoding")
@@ -65,9 +85,8 @@ private Response decompress(final Response response) throws IOException {
6585
}
6686

6787
private Boolean isCompressed(Response response) {
68-
return response.header("Content-Encoding") != null
69-
&& (response.header("Content-Encoding").toLowerCase().equals("gzip")
70-
|| response.header("Content-Encoding").toLowerCase().equals("deflate")
71-
|| response.header("Content-Encoding").toLowerCase().equals("br"));
88+
String contentEncoding = response.header("Content-Encoding");
89+
return contentEncoding != null
90+
&& (contentEncoding.equalsIgnoreCase("gzip") || contentEncoding.equalsIgnoreCase("deflate") || contentEncoding.equalsIgnoreCase("br"));
7291
}
7392
}

SecureHttpClient.Test/HttpTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public async Task HttpTest_Compression_Gzip_WithRequestHeader()
5757
[Fact]
5858
public async Task HttpTest_Compression_Deflate_WithoutRequestHeader()
5959
{
60-
const string page = @"https://httpbingo.org/deflate";
60+
const string page = @"https://httpbingo.org/deflate"; // has zlib header (RFC 1951)
6161
var result = await GetAsync(page).ReceiveString();
6262
var json = JsonDocument.Parse(result);
6363
var url = json.RootElement.GetProperty("deflated").GetBoolean();

0 commit comments

Comments
 (0)