Skip to content

Commit 67bd227

Browse files
committed
Fixed GZIPInputStream Explicit termination method 'end' not called error, Fixes android-async-http#613
1 parent a11ee91 commit 67bd227

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

library/src/main/java/com/loopj/android/http/AsyncHttpClient.java

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import java.io.InputStream;
7474
import java.io.OutputStream;
7575
import java.io.PushbackInputStream;
76+
import java.lang.reflect.Field;
7677
import java.net.URI;
7778
import java.util.Collections;
7879
import java.util.HashMap;
@@ -1262,27 +1263,72 @@ private HttpEntityEnclosingRequestBase addEntityToRequestBase(HttpEntityEnclosin
12621263
return requestBase;
12631264
}
12641265

1266+
/**
1267+
* This horrible hack is required on Android, due to implementation of BasicManagedEntity, which
1268+
* doesn't chain call consumeContent on underlying wrapped HttpEntity
1269+
*
1270+
* @param entity HttpEntity, may be null
1271+
*/
1272+
public static void endEntityViaReflection(HttpEntity entity) {
1273+
if (entity instanceof HttpEntityWrapper) {
1274+
try {
1275+
Field f = null;
1276+
Field[] fields = HttpEntityWrapper.class.getDeclaredFields();
1277+
for (Field ff : fields) {
1278+
if (ff.getName().equals("wrappedEntity")) {
1279+
f = ff;
1280+
break;
1281+
}
1282+
}
1283+
if (f != null) {
1284+
f.setAccessible(true);
1285+
HttpEntity wrapped = (HttpEntity) f.get(entity);
1286+
if (wrapped != null) {
1287+
wrapped.consumeContent();
1288+
}
1289+
}
1290+
} catch (Throwable t) {
1291+
Log.e(LOG_TAG, "wrappedEntity consume", t);
1292+
}
1293+
}
1294+
}
1295+
12651296
/**
12661297
* Enclosing entity to hold stream of gzip decoded data for accessing HttpEntity contents
12671298
*/
12681299
private static class InflatingEntity extends HttpEntityWrapper {
1300+
12691301
public InflatingEntity(HttpEntity wrapped) {
12701302
super(wrapped);
12711303
}
12721304

1305+
InputStream wrappedStream;
1306+
PushbackInputStream pushbackStream;
1307+
GZIPInputStream gzippedStream;
1308+
12731309
@Override
12741310
public InputStream getContent() throws IOException {
1275-
PushbackInputStream content = new PushbackInputStream(wrappedEntity.getContent(), 2);
1276-
if (isInputStreamGZIPCompressed(content)) {
1277-
return new GZIPInputStream(content);
1311+
wrappedStream = wrappedEntity.getContent();
1312+
pushbackStream = new PushbackInputStream(wrappedStream, 2);
1313+
if (isInputStreamGZIPCompressed(pushbackStream)) {
1314+
gzippedStream = new GZIPInputStream(pushbackStream);
1315+
return gzippedStream;
12781316
} else {
1279-
return content;
1317+
return pushbackStream;
12801318
}
12811319
}
12821320

12831321
@Override
12841322
public long getContentLength() {
12851323
return -1;
12861324
}
1325+
1326+
@Override
1327+
public void consumeContent() throws IOException {
1328+
AsyncHttpClient.silentCloseInputStream(wrappedStream);
1329+
AsyncHttpClient.silentCloseInputStream(pushbackStream);
1330+
AsyncHttpClient.silentCloseInputStream(gzippedStream);
1331+
super.consumeContent();
1332+
}
12871333
}
12881334
}

library/src/main/java/com/loopj/android/http/AsyncHttpResponseHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ byte[] getResponseData(HttpEntity entity) throws IOException {
411411
}
412412
} finally {
413413
AsyncHttpClient.silentCloseInputStream(instream);
414+
AsyncHttpClient.endEntityViaReflection(entity);
414415
}
415416
responseBody = buffer.toByteArray();
416417
} catch (OutOfMemoryError e) {

0 commit comments

Comments
 (0)