BREAKING: Android: Support withCredentials flag in XHRs

Summary:
Corresponding iOS PR: #12275

Respect the withCredentials XMLHttpRequest flag for sending cookies with requests. This can reduce payload sizes where large cookies are set for domains.

This should fix #5347.

This is a breaking change because it alters the default behavior of XHR. Prior to this change, XHR would send cookies by default. After this change, by default, XHR does not send cookies which is consistent with the default behavior of XHR on web for cross-site requests. Developers can restore the previous behavior by passing `true` for XHR's `withCredentials` argument.

**Test plan (required)**

Verified in a test app that XHR works properly when specifying `withCredentials` as `true`, `false`, and `undefined`. Also, my team uses this change in our app.

Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/12276

Differential Revision: D4673646

Pulled By: ericvicenti

fbshipit-source-id: 924c230c9df72071b3cf9151c3ac201905ac28a5
This commit is contained in:
Adam Comella 2017-04-10 22:32:38 -07:00 committed by Facebook Github Bot
parent ecd0df01af
commit e544563bd2
3 changed files with 31 additions and 13 deletions

View File

@ -56,7 +56,8 @@ class RCTNetworking extends NativeEventEmitter {
responseType: 'text' | 'base64', responseType: 'text' | 'base64',
incrementalUpdates: boolean, incrementalUpdates: boolean,
timeout: number, timeout: number,
callback: (requestId: number) => any callback: (requestId: number) => any,
withCredentials: boolean
) { ) {
const body = convertRequestBody(data); const body = convertRequestBody(data);
if (body && body.formData) { if (body && body.formData) {
@ -74,7 +75,8 @@ class RCTNetworking extends NativeEventEmitter {
{...body, trackingName}, {...body, trackingName},
responseType, responseType,
incrementalUpdates, incrementalUpdates,
timeout timeout,
withCredentials
); );
callback(requestId); callback(requestId);
} }

View File

@ -36,6 +36,7 @@ import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEm
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Callback; import okhttp3.Callback;
import okhttp3.CookieJar;
import okhttp3.Headers; import okhttp3.Headers;
import okhttp3.Interceptor; import okhttp3.Interceptor;
import okhttp3.JavaNetCookieJar; import okhttp3.JavaNetCookieJar;
@ -167,7 +168,8 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
ReadableMap data, ReadableMap data,
final String responseType, final String responseType,
final boolean useIncrementalUpdates, final boolean useIncrementalUpdates,
int timeout) { int timeout,
boolean withCredentials) {
Request.Builder requestBuilder = new Request.Builder().url(url); Request.Builder requestBuilder = new Request.Builder().url(url);
if (requestId != 0) { if (requestId != 0) {
@ -177,6 +179,10 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
final RCTDeviceEventEmitter eventEmitter = getEventEmitter(executorToken); final RCTDeviceEventEmitter eventEmitter = getEventEmitter(executorToken);
OkHttpClient.Builder clientBuilder = mClient.newBuilder(); OkHttpClient.Builder clientBuilder = mClient.newBuilder();
if (!withCredentials) {
clientBuilder.cookieJar(CookieJar.NO_COOKIES);
}
// If JS is listening for progress updates, install a ProgressResponseBody that intercepts the // If JS is listening for progress updates, install a ProgressResponseBody that intercepts the
// response and counts bytes received. // response and counts bytes received.
if (useIncrementalUpdates) { if (useIncrementalUpdates) {

View File

@ -100,7 +100,8 @@ public class NetworkingModuleTest {
/* body */ null, /* body */ null,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class); ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class);
verify(httpClient).newCall(argumentCaptor.capture()); verify(httpClient).newCall(argumentCaptor.capture());
@ -135,7 +136,8 @@ public class NetworkingModuleTest {
/* body */ null, /* body */ null,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
verifyErrorEmit(emitter, 0); verifyErrorEmit(emitter, 0);
} }
@ -166,7 +168,8 @@ public class NetworkingModuleTest {
body, body,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
verifyErrorEmit(emitter, 0); verifyErrorEmit(emitter, 0);
} }
@ -227,7 +230,8 @@ public class NetworkingModuleTest {
body, body,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class); ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class);
verify(httpClient).newCall(argumentCaptor.capture()); verify(httpClient).newCall(argumentCaptor.capture());
@ -270,7 +274,8 @@ public class NetworkingModuleTest {
null, null,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class); ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class);
verify(httpClient).newCall(argumentCaptor.capture()); verify(httpClient).newCall(argumentCaptor.capture());
Headers requestHeaders = argumentCaptor.getValue().headers(); Headers requestHeaders = argumentCaptor.getValue().headers();
@ -324,7 +329,8 @@ public class NetworkingModuleTest {
body, body,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
// verify url, method, headers // verify url, method, headers
ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class); ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class);
@ -389,7 +395,8 @@ public class NetworkingModuleTest {
body, body,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
// verify url, method, headers // verify url, method, headers
ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class); ArgumentCaptor<Request> argumentCaptor = ArgumentCaptor.forClass(Request.class);
@ -492,7 +499,8 @@ public class NetworkingModuleTest {
body, body,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
/* timeout */ 0); /* timeout */ 0,
/* withCredentials */ false);
// verify RequestBodyPart for image // verify RequestBodyPart for image
PowerMockito.verifyStatic(times(1)); PowerMockito.verifyStatic(times(1));
@ -556,7 +564,8 @@ public class NetworkingModuleTest {
null, null,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
0); /* timeout */ 0,
/* withCredentials */ false);
} }
verify(httpClient, times(3)).newCall(any(Request.class)); verify(httpClient, times(3)).newCall(any(Request.class));
@ -606,7 +615,8 @@ public class NetworkingModuleTest {
null, null,
/* responseType */ "text", /* responseType */ "text",
/* useIncrementalUpdates*/ true, /* useIncrementalUpdates*/ true,
0); /* timeout */ 0,
/* withCredentials */ false);
} }
verify(httpClient, times(3)).newCall(any(Request.class)); verify(httpClient, times(3)).newCall(any(Request.class));