Fix multiple set-cookie not aggregated correctly in response headers (#27066)

Summary:
Multiple `set-cookie` headers should be aggregated as one `set-cookie` with values in a comma separated list. It is working as expected on iOS but not on Android. On Android, only the last one is preserved

The problem arises because `NetworkingModule.translateHeaders()` uses `WritableNativeMap` as the translated headers but uses both native and non-native methods. The mixup causes out of sync data that both sets of methods do no agree. A simple fix is to use `Bundle` as the storage and only convert it to `WritableMap` at the end in one go

Related issues: https://github.com/facebook/react-native/issues/26280, https://github.com/facebook/react-native/issues/21795, https://github.com/facebook/react-native/issues/23185

## Changelog

[Android] [Fixed] - Fix multiple headers of the same name (e.g. `set-cookie`) not aggregated correctly
Pull Request resolved: https://github.com/facebook/react-native/pull/27066

Test Plan:
A mock api, https://demo6524373.mockable.io/, will return 2 `set-cookie` as follows:
```
set-cookie: cookie1=value1
set-cookie: cookie2=value2
```

Verify the following will print the `set-cookie` with a value `cookie1=value1, cookie2=value2`
```javascript
  fetch('https://demo6524373.mockable.io/')
    .then(response => {
      console.log(response.headers);
    });
```
On iOS, `set-cookie` will have `cookie1=value1, cookie2=value2` while on Android it will have `cookie2=value2` (preserving only the last one)

Differential Revision: D18298933

Pulled By: cpojer

fbshipit-source-id: ce53cd41d7c6de0469700617900f30a7d0914c26
This commit is contained in:
Vincent Cheung
2019-11-05 03:28:05 -08:00
committed by Facebook Github Bot
parent a3b0804867
commit 1df8bd4932
@@ -8,6 +8,7 @@
package com.facebook.react.modules.network;
import android.net.Uri;
import android.os.Bundle;
import android.util.Base64;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
@@ -629,18 +630,18 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
}
private static WritableMap translateHeaders(Headers headers) {
WritableMap responseHeaders = Arguments.createMap();
Bundle responseHeaders = new Bundle();
for (int i = 0; i < headers.size(); i++) {
String headerName = headers.name(i);
// multiple values for the same header
if (responseHeaders.hasKey(headerName)) {
if (responseHeaders.containsKey(headerName)) {
responseHeaders.putString(
headerName, responseHeaders.getString(headerName) + ", " + headers.value(i));
} else {
responseHeaders.putString(headerName, headers.value(i));
}
}
return responseHeaders;
return Arguments.fromBundle(responseHeaders);
}
@ReactMethod