Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fetch response.text() returning undefined on iOS works on Android #37113

Open
pke opened this issue Apr 27, 2023 · 8 comments
Open

fetch response.text() returning undefined on iOS works on Android #37113

pke opened this issue Apr 27, 2023 · 8 comments
Labels
Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍 🌐Networking Related to a networking API. Newer Patch Available Platform: Android Android applications. Platform: iOS iOS applications.

Comments

@pke
Copy link

pke commented Apr 27, 2023

Description

reading textual information from a http (not https!) fetch response is not possible on iOS. It always returns undefined.

I have added the required ATS excemptions in my iOS app like this:

<key>streamingsoundtracks.com</key>
<dict>
	<key>NSExceptionAllowsInsecureHTTPLoads</key>
	<true/>
	<key>NSIncludesSubdomains</key>
	<true/>
</dict>

React Native Version

0.71.7

Output of npx react-native info

System:
OS: macOS 13.3.1
CPU: (10) arm64 Apple M1 Max
Memory: 42.66 MB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 16.18.1 - ~/.nvm/versions/node/v16.18.1/bin/node
Yarn: 1.22.19 - ~/.yarn/bin/yarn
npm: 8.19.2 - ~/.nvm/versions/node/v16.18.1/bin/npm
Watchman: 2022.09.26.00 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.11.3 - /Users/pkursawe/.gem/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1
Android SDK:
API Levels: 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33
Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.0, 30.0.1, 30.0.2, 30.0.3, 31.0.0, 33.0.0
System Images: android-22 | Google APIs Intel x86 Atom, android-23 | Google APIs Intel x86 Atom, android-24 | Google APIs Intel x86 Atom, android-25 | Google APIs Intel x86 Atom, android-26 | Google APIs Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-28 | Google ARM64-V8a Play ARM 64 v8a, android-29 | Google APIs Intel x86 Atom, android-29 | Google Play ARM 64 v8a, android-29 | Google Play Intel x86 Atom, android-30 | Google APIs Intel x86 Atom, android-30 | Google Play ARM 64 v8a, android-31 | Google Play ARM 64 v8a, android-32 | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8512546
Xcode: 14.2/14C18 - /usr/bin/xcodebuild
Languages:
Java: javac 18 - /usr/local/opt/openjdk/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: Not Found
react-native: Not Found
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

fetch( "http://streamingsoundtracks.com/modules/ClearChat/common/log.php")
  .then(response => response.text())

Snack, code example, screenshot, or link to a repository

https://snack.expo.dev/bgysLbFYW

@github-actions
Copy link

⚠️ Newer Version of React Native is Available!
ℹ️ You are on a supported minor version, but it looks like there's a newer patch available. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

@github-actions github-actions bot added Newer Patch Available Platform: Android Android applications. Platform: iOS iOS applications. 🌐Networking Related to a networking API. labels Apr 27, 2023
@pke
Copy link
Author

pke commented Apr 27, 2023

Still buggy on newest version. See snack where it also doesn't work in ios but is fine in Android

@cortinico cortinico added the Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. label Apr 27, 2023
@LunatiqueCoder
Copy link

LunatiqueCoder commented Feb 14, 2024

We also have issues with .json(). Here's another reproduction code with any new React Native project:

import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import { StyleSheet, Text, View } from 'react-native';

 export default function App() {
  useEffect(() => {

    const data = fetch('https://ed.engdis.com/Runtime/Content/Reading/fdrobr/fdrobr01.json').then(res=>res.json().then(res=>console.log('res',res)))

  }, [])

  return (
    <View style={styles.container}>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

@pke
Copy link
Author

pke commented Feb 15, 2024

@LunatiqueCoder the bug occurs only with http not https if I remember correctly on my side

@LunatiqueCoder
Copy link

@pke You can try the reproduction example I provided, I'm pretty sure you will see similar or exact same results:

  • fetch response.text()/.json() returning undefined on iOS but works on Android

@mbpictures
Copy link

mbpictures commented Mar 10, 2024

I encountered the exact same issue with https. No errors in Logs, status code is 200, but the result of await response.text() returns undefined? Has anyone found a solution for this?

@huzhanbo1996
Copy link

huzhanbo1996 commented May 14, 2024

Hi all,

By digging into this issue, I found that there are two factors causing this failure.

  1. Apple Application Transport Security (ATS) is causing http (non-https) request fails, see stackoverflow answer for this. Reminder, only the NSExceptionDomains works for me, the NSAllowsArbitraryLoads does not. As this is an Apple policy, we probably won't fix it on RN. cc @cortinico @NickGerleman

  2. The other problem is decoding: both response provided by @pke and @LunatiqueCoder are not valid UTF-8 encoded. The decoding perform differently on iOS and Android (inside FileReader): on iOS the decode error causes an empty response, and on Android it omits the error and provides a possible incorrect decoded string. Though Android is returning a string, but the behavior is unspecified, so the returned string may be incorrect.

Here is a workaround by manually indicating the encoding type and access directly Blob. Forgive my poor JS writing :D

  const fileReaderReady = (reader) => {
        return new Promise(function(resolve, reject) {
          reader.onload = function() {
            resolve(reader.result);
          };
          reader.onerror = function() {
            reject(reader.error);
          };
        })
      }

    fetch("https://ed.engdis.com/Runtime/Content/Reading/fdrobr/fdrobr01.json")
    .then(resp => {
      resp.blob().then(blob => {
        var reader = new FileReader();
        var ans = fileReaderReady(reader);
        // !!! replace to your encode type here !!! 'ISO-8859-1'
        reader.readAsText(blob, 'ISO-8859-1');
        // !!! replace to your encode type here !!! 'ISO-8859-1'
        ans.then((respAsText) => {
            console.log(respAsText);
        }).catch(e => console.log(e));
      }).catch(e => console.log(e))
        
      })
    .catch(e => console.log(e))

At last, what we can do:

  1. At least, we should report the decode error on iOS (also on Android if this API break is acceptable), so developers can debug the process.

  2. Ultimate solution: align response.text() with W3C standard. It is difficult and I don't see any short path. The problems we need to solve for the alignment:

  • Get the encoding type from MINE-TYPE (and BOM sniff)
  • Pass the encoding type into FileReader, this chain is inside fetch Polyfill, so we need to modify third party code
  • Align the behavior of invalid code point in this spec

@pke
Copy link
Author

pke commented May 14, 2024

thanks @huzhanbo1996 for checking it out. An invalid encoding has not come to my mind, but it makes sense now. Nobody cared about that in the days this website was created. I'll try your workaround.
I think the RN should not try to detect the proper encoding, but it just should error out correctly when calling json/text()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍 🌐Networking Related to a networking API. Newer Patch Available Platform: Android Android applications. Platform: iOS iOS applications.
Projects
None yet
Development

No branches or pull requests

5 participants