Send large responses in chunks
Summary: It's common for responses to be completely missing in the network inspector. This is because they are larger than can be serialized in one go on some devices, so we drop all messages larger than 1MB. This changes the android client to send large responses in individually serialized batches. This way we avoid running out of memory and can still send arbitrarily large payloads. Changelog: Android network inspector can now handle responses large than 1MB. Reviewed By: passy Differential Revision: D22999905 fbshipit-source-id: ff4eb8fa72a7e42ea90d12ffe0f20c6d1e58b7e5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0065ddedd7
commit
9efcbdceaf
@@ -12,7 +12,9 @@ import com.facebook.flipper.core.ErrorReportingRunnable;
|
||||
import com.facebook.flipper.core.FlipperArray;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.plugins.common.BufferingFlipperPlugin;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class NetworkFlipperPlugin extends BufferingFlipperPlugin implements NetworkReporter {
|
||||
public static final String ID = "Network";
|
||||
@@ -64,18 +66,42 @@ public class NetworkFlipperPlugin extends BufferingFlipperPlugin implements Netw
|
||||
responseInfo.body = null;
|
||||
}
|
||||
|
||||
final FlipperObject response =
|
||||
new FlipperObject.Builder()
|
||||
.put("id", responseInfo.requestId)
|
||||
.put("timestamp", responseInfo.timeStamp)
|
||||
.put("status", responseInfo.statusCode)
|
||||
.put("reason", responseInfo.statusReason)
|
||||
.put("headers", toFlipperObject(responseInfo.headers))
|
||||
.put("isMock", responseInfo.isMock)
|
||||
.put("data", toBase64(responseInfo.body))
|
||||
.build();
|
||||
int numChunks =
|
||||
responseInfo.body == null
|
||||
? 1
|
||||
: (int) Math.ceil((double) responseInfo.body.length / MAX_BODY_SIZE_IN_BYTES);
|
||||
|
||||
send("newResponse", response);
|
||||
for (int i = 0; i < numChunks; i++) {
|
||||
byte[] chunk =
|
||||
responseInfo.body == null
|
||||
? null
|
||||
: Arrays.copyOfRange(
|
||||
responseInfo.body,
|
||||
i * MAX_BODY_SIZE_IN_BYTES,
|
||||
Math.min((i + 1) * MAX_BODY_SIZE_IN_BYTES, responseInfo.body.length));
|
||||
final FlipperObject response =
|
||||
i == 0
|
||||
? new FlipperObject.Builder()
|
||||
.put("id", responseInfo.requestId)
|
||||
.put("timestamp", responseInfo.timeStamp)
|
||||
.put("status", responseInfo.statusCode)
|
||||
.put("reason", responseInfo.statusReason)
|
||||
.put("headers", toFlipperObject(responseInfo.headers))
|
||||
.put("isMock", responseInfo.isMock)
|
||||
.put("data", toBase64(chunk))
|
||||
.put("totalChunks", numChunks)
|
||||
.put("index", i)
|
||||
.build()
|
||||
: new FlipperObject.Builder()
|
||||
.put("id", responseInfo.requestId)
|
||||
.put("timestamp", responseInfo.timeStamp)
|
||||
.put("totalChunks", numChunks)
|
||||
.put("index", i)
|
||||
.put("data", toBase64(chunk))
|
||||
.build();
|
||||
|
||||
send(numChunks == 1 ? "newResponse" : "partialResponse", response);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,7 +125,7 @@ public class NetworkFlipperPlugin extends BufferingFlipperPlugin implements Netw
|
||||
job.run();
|
||||
}
|
||||
|
||||
private String toBase64(byte[] bytes) {
|
||||
private String toBase64(@Nullable byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -122,10 +148,6 @@ public class NetworkFlipperPlugin extends BufferingFlipperPlugin implements Netw
|
||||
return false;
|
||||
}
|
||||
|
||||
if (responseInfo.body != null && responseInfo.body.length > MAX_BODY_SIZE_IN_BYTES) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return contentType.value.contains("image/")
|
||||
|| contentType.value.contains("video/")
|
||||
|| contentType.value.contains("application/zip");
|
||||
|
||||
@@ -9,6 +9,7 @@ package com.facebook.flipper.plugins.network;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface NetworkReporter {
|
||||
void reportRequest(RequestInfo requestInfo);
|
||||
@@ -54,7 +55,7 @@ public interface NetworkReporter {
|
||||
public int statusCode;
|
||||
public String statusReason;
|
||||
public List<Header> headers = new ArrayList<>();
|
||||
public byte[] body;
|
||||
public @Nullable byte[] body;
|
||||
public boolean isMock = false;
|
||||
|
||||
public Header getFirstHeader(final String name) {
|
||||
|
||||
Reference in New Issue
Block a user