HTTP response headers with the same key are not processed properly. [The expected behaviour is that the values of the identical keys are combined to a string separated by a comma]
See original GitHub issueEnvironment
OS: macOS High Sierra 10.13.6 Node: 8.12.0 Yarn: Not Found npm: 6.4.1 Watchman: 4.9.0 Xcode: Xcode 10.0 Build version 10A255 Android Studio: 3.2 AI-181.5540.7.32.5014246
Packages: (wanted => installed) react: 16.3.1 => 16.3.1 react-native: https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz => 0.55.4
Description
I have an issue supporting multiple cookies passed on the response header on Android. I tracked the issue to line 607
in translateHeaders
function in NetworkingModule.java
file from the link below.
I debugged and realised that the code that checks if the headerMap of type WritableMap
has the header key already in it is always failing and defaulting to the “Else” part which always replaces the previous key and value every time instead of combining previous key’s value string separated by a comma as it is supposed to. Due to this, only one cookie is always passed to React side.
Furthermore, the code I mentioned above use ReadableNativeMap
class which holds the actual key-value map as an instance variable. getLocalMap
function in ReadableNativeMap
class is used to retrieve the “mLocalMap” variable but always return an object that doesn’t have values hence the code inside NetworkingModule
is not doing what it is supposed to.
Lastly, I’m aware that my environment info state that I’m using react-native from Expo https://github.com/expo/react-native, however the code that I found an issue on, Expo also use it as is from https://github.com/facebook/react-native hence I created an issue here.
Reproducible Demo
Pass multiple headers with the same key from a network request.
In my case I’m getting response headers with multiple cookies with key “Set-Cookie” from a network request, but after it has been processed by the code I mentioned above, there is always one.
Sample response header with multiple cookies similar to what get from the server.
Server: Example Date: Tue, 16 Oct 2018 10:35:21 GMT Content-Type: application/json;charset=UTF-8 Connection: keep-alive Expires: 0 X-B3-TraceId: d6745404c1d2a7fb Set-Cookie: MyDBTokenForApps=6c785634-d62d-32a2-a4f7-8c1e0f42a93f; path=/; secure; Max-Age=43198; Expires=Tue, 16-Oct-2018 22:35:19 GMT Set-Cookie: anotherCookie=1$E4AAA5C9C37865158B02402AFFDB7856; path=/; domain=.example.co.za; secure X-XSS-Protection: 1; mode=block X-Frame-Options: DENY X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000 ; includeSubDomains Instance: /CSG/pool_vcoza_summer_80 10.112.205.215 80 Vary: Accept-Encoding Transfer-Encoding: chunked Cache-Control: public, max-age=0
After this has been processed by translateHeaders
function, only one cookie header that was processed last remains.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:6
- Comments:41 (5 by maintainers)
Top GitHub Comments
Hello, I had the same problem here and analysed the internal issue:
The problem is a combination of
NetworkingModule.java
and the usage ofWritableNativeMap
. The functiontranslateHeaders
maps the OKHTTP header objekt to a React Native header map. Headers with the same key was overridden because thehasKey
method always return false.https://github.com/facebook/react-native/blob/9895d011374e655bcaeb390167abafb9c01fef18/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java#L647-L661
That
hasKey
always return false is an implementation error inReadableNativeMap
andWritableNativeMap
(which extends the readable map). This native maps supports two different modes, which can be enabled and disabled for all maps with a static booleanuseNativeAccessor
.This flag defines if the ReadableNativeMap reads data from a native map or a internal (java.util.) HashMap.
But the problem was that WritableNativeMap always writes into the native map and never uses the (Readable) internal HashMap.
That was the reason why
hasKey
always return null ifuseNativeAccessor
was false and only one header was returned bytranslateHeaders
.Like said by @hey99xx in https://github.com/facebook/react-native/issues/21795#issuecomment-430384534 and by @Return-1 https://github.com/facebook/react-native/issues/23005#issuecomment-457107736 its possible to activate the this native accessor, if you add this code to your own/project
MainActivity.java
:Add this imports:
And this add the beginning of the
createReactActivityDelegate
method, before your application was loaded.For me this works fine. But notice that this global flag may cause some other troubles.
I also started to fix this behaviour in the latest React Native 0.59.3 release, but notice than that the master version of ReadableNativeMap/WritableNativeMap was already changed.
The commits https://github.com/facebook/react-native/commit/b257e06bc6c29236a1a19f645fb46b85b2ffc4d2 and https://github.com/facebook/react-native/commit/a062b34493f07b28378de2772914d838cb28e3d8 by FB eng @sahrens changed/removed the useNativeAccessor behaviour, so I hope this issue was also fixed with the next/upcoming minor release 0.60.0. 🙌
(I couldn’t test the new version yet, because running from the npm package (also with sourcecode changes) works fine for me, but the sourcecode version of RN let fail some of my 3rd party libraries. I’m looking forward for a RC of 0.60.0 and maybe will update this text here then.)
@sahrens This issue still persists on 0.60.4, and the workaround doesn’t work since you removed it. Please look into it, as it makes react native with cookie based auth unusable