Skip to content

Commit 3e4cf0e

Browse files
allengleyzerfacebook-github-bot
authored andcommittedNov 14, 2017
Added progress updates for all XMLHttpRequest upload types
Summary: Previously, only form-data request bodies emitted upload progress updates. Now, other request body types will also emit updates. Addresses issues: #15724 #11853 This is a bug fix for functionality that's missing on Android. These events are already working correctly on iOS. Run the following code on Android, and ensure that events are being sent: ``` const fileUri = 'file:///my_file.dat'; const url = 'http://my_post_url.com/'; const xhr = new XMLHttpRequest(); xhr.upload.onprogress = (event) => { console.log('progress: ' + event.loaded + ' / ' + event.total); } xhr.onreadystatechange = () => {if (xhr.readyState === 4) console.log('done');} console.log('start'); xhr.open('POST', url); xhr.send({ uri: fileUri }); // sending a file (wasn't sending progress) xhr.send("some big string"); // sending a string (wasn't sending progress) const formData = new FormData(); formData.set('test', 'data'); xhr.send(formData); // sending form data (was already working) ``` [ANDROID] [BUGFIX] [XMLHttpRequest] - Added progress updates for all XMLHttpRequest upload types Previously, only form-data request bodies emitted upload progress updates. Now, other request body types will also emit updates. Addresses issues: #15724 #11853 Closes #16541 Differential Revision: D6325252 Pulled By: hramos fbshipit-source-id: 4fe617216293e6f451e2a1af4fa872e8f56d4f93
1 parent 58edf02 commit 3e4cf0e

File tree

2 files changed

+42
-30
lines changed

2 files changed

+42
-30
lines changed
 

‎ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java

+35-28
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
235235
String contentEncoding = requestHeaders.get(CONTENT_ENCODING_HEADER_NAME);
236236
requestBuilder.headers(requestHeaders);
237237

238+
RequestBody requestBody;
238239
if (data == null) {
239-
requestBuilder.method(method, RequestBodyUtil.getEmptyBody(method));
240+
requestBody = RequestBodyUtil.getEmptyBody(method);
240241
} else if (data.hasKey(REQUEST_BODY_KEY_STRING)) {
241242
if (contentType == null) {
242243
ResponseUtil.onRequestError(
@@ -249,14 +250,13 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
249250
String body = data.getString(REQUEST_BODY_KEY_STRING);
250251
MediaType contentMediaType = MediaType.parse(contentType);
251252
if (RequestBodyUtil.isGzipEncoding(contentEncoding)) {
252-
RequestBody requestBody = RequestBodyUtil.createGzip(contentMediaType, body);
253+
requestBody = RequestBodyUtil.createGzip(contentMediaType, body);
253254
if (requestBody == null) {
254255
ResponseUtil.onRequestError(eventEmitter, requestId, "Failed to gzip request body", null);
255256
return;
256257
}
257-
requestBuilder.method(method, requestBody);
258258
} else {
259-
requestBuilder.method(method, RequestBody.create(contentMediaType, body));
259+
requestBody = RequestBody.create(contentMediaType, body);
260260
}
261261
} else if (data.hasKey(REQUEST_BODY_KEY_BASE64)) {
262262
if (contentType == null) {
@@ -269,9 +269,7 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
269269
}
270270
String base64String = data.getString(REQUEST_BODY_KEY_BASE64);
271271
MediaType contentMediaType = MediaType.parse(contentType);
272-
requestBuilder.method(
273-
method,
274-
RequestBody.create(contentMediaType, ByteString.decodeBase64(base64String)));
272+
requestBody = RequestBody.create(contentMediaType, ByteString.decodeBase64(base64String));
275273
} else if (data.hasKey(REQUEST_BODY_KEY_URI)) {
276274
if (contentType == null) {
277275
ResponseUtil.onRequestError(
@@ -292,9 +290,7 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
292290
null);
293291
return;
294292
}
295-
requestBuilder.method(
296-
method,
297-
RequestBodyUtil.create(MediaType.parse(contentType), fileInputStream));
293+
requestBody = RequestBodyUtil.create(MediaType.parse(contentType), fileInputStream);
298294
} else if (data.hasKey(REQUEST_BODY_KEY_FORMDATA)) {
299295
if (contentType == null) {
300296
contentType = "multipart/form-data";
@@ -305,28 +301,16 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
305301
if (multipartBuilder == null) {
306302
return;
307303
}
308-
309-
requestBuilder.method(
310-
method,
311-
RequestBodyUtil.createProgressRequest(
312-
multipartBuilder.build(),
313-
new ProgressListener() {
314-
long last = System.nanoTime();
315-
316-
@Override
317-
public void onProgress(long bytesWritten, long contentLength, boolean done) {
318-
long now = System.nanoTime();
319-
if (done || shouldDispatch(now, last)) {
320-
ResponseUtil.onDataSend(eventEmitter, requestId, bytesWritten, contentLength);
321-
last = now;
322-
}
323-
}
324-
}));
304+
requestBody = multipartBuilder.build();
325305
} else {
326306
// Nothing in data payload, at least nothing we could understand anyway.
327-
requestBuilder.method(method, RequestBodyUtil.getEmptyBody(method));
307+
requestBody = RequestBodyUtil.getEmptyBody(method);
328308
}
329309

310+
requestBuilder.method(
311+
method,
312+
wrapRequestBodyWithProgressEmitter(requestBody, eventEmitter, requestId));
313+
330314
addRequest(requestId);
331315
client.newCall(requestBuilder.build()).enqueue(
332316
new Callback() {
@@ -394,6 +378,29 @@ public void onResponse(Call call, Response response) throws IOException {
394378
});
395379
}
396380

381+
private RequestBody wrapRequestBodyWithProgressEmitter(
382+
final RequestBody requestBody,
383+
final RCTDeviceEventEmitter eventEmitter,
384+
final int requestId) {
385+
if(requestBody == null) {
386+
return null;
387+
}
388+
return RequestBodyUtil.createProgressRequest(
389+
requestBody,
390+
new ProgressListener() {
391+
long last = System.nanoTime();
392+
393+
@Override
394+
public void onProgress(long bytesWritten, long contentLength, boolean done) {
395+
long now = System.nanoTime();
396+
if (done || shouldDispatch(now, last)) {
397+
ResponseUtil.onDataSend(eventEmitter, requestId, bytesWritten, contentLength);
398+
last = now;
399+
}
400+
}
401+
});
402+
}
403+
397404
private void readWithProgress(
398405
RCTDeviceEventEmitter eventEmitter,
399406
int requestId,

‎ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ public WritableMap answer(InvocationOnMock invocation) throws Throwable {
200200

201201
@Test
202202
public void testSuccessfulPostRequest() throws Exception {
203+
RCTDeviceEventEmitter emitter = mock(RCTDeviceEventEmitter.class);
204+
ReactApplicationContext context = mock(ReactApplicationContext.class);
205+
when(context.getJSModule(any(Class.class))).thenReturn(emitter);
206+
203207
OkHttpClient httpClient = mock(OkHttpClient.class);
204208
when(httpClient.newCall(any(Request.class))).thenAnswer(new Answer<Object>() {
205209
@Override
@@ -211,12 +215,13 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
211215
OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class);
212216
when(clientBuilder.build()).thenReturn(httpClient);
213217
when(httpClient.newBuilder()).thenReturn(clientBuilder);
214-
NetworkingModule networkingModule =
215-
new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient);
218+
NetworkingModule networkingModule = new NetworkingModule(context, "", httpClient);
216219

217220
JavaOnlyMap body = new JavaOnlyMap();
218221
body.putString("string", "This is request body");
219222

223+
mockEvents();
224+
220225
networkingModule.sendRequest(
221226
"POST",
222227
"http://somedomain/bar",

0 commit comments

Comments
 (0)
Please sign in to comment.