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("aaa") has incorrect behavior #7436

Closed
5 tasks done
cancan101 opened this issue May 7, 2016 · 20 comments
Closed
5 tasks done

fetch("aaa") has incorrect behavior #7436

cancan101 opened this issue May 7, 2016 · 20 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@cancan101
Copy link
Contributor

cancan101 commented May 7, 2016

Unable to catch error thrown from fetch with invalid url. Instead I get a message about "unexpected url".

  • Provide a minimal code snippet / rnplay example that reproduces the bug.
try {
   fetch("aaa");
} catch (ex) { }
  • Provide screenshots where appropriate
    image
  • What's the version of React Native you're using?
    0.24.1
  • Does this occur on iOS, Android or both?
    Android
  • Are you using Mac, Linux or Windows?
    OS X
@satya164
Copy link
Contributor

satya164 commented May 8, 2016

This is tricky. The error thrown is from the native side, and due to the async nature of the bridge, it won't be possible to throw an error on JS side. I see 2 options,

  1. Do URL validation on JS side, so we can throw the error synchronously
  2. Reject the promise instead of crashing/showing redbox

cc @dmmiller @nicklockwood

@ide
Copy link
Contributor

ide commented May 8, 2016

I think we should always do 2 and sometimes do 1 as well. That is, convert all native failures to promise rejections, but also do extra validation in JS when we think we can provide better error messages closer to the source of the error.

@satya164
Copy link
Contributor

satya164 commented May 8, 2016

@cancan101 Want to a PR?

@nicklockwood
Copy link
Contributor

+1 for JS URL validation, since it will ensure consistency in behavior between platforms, as well as all the other listed benefits. We'll need to keep the validation on the native side as a backup too though (iOS will crash hard for certain invalid url strings).

@cancan101
Copy link
Contributor Author

I should add that on ios the promise is rejected as expected for this invalid url string.

@lacker lacker changed the title Unable to catch error thrown from fetch with invalid url fetch("aaa") has incorrect behavior Oct 21, 2016
@lacker
Copy link
Contributor

lacker commented Oct 21, 2016

Hmm, I don't think rejecting the promise is the correct behavior. So actually I think both ios and Android are doing it wrong, if iOS rejects the promise and Android redboxes. The fetch API only rejects the promise when there's a network error. With an invalid URL I think you are supposed to get a successful promise, but it returns something with an error object. That's how it appears to work in Chrome, for example - this sample code prints "1" indicating the promise resolved successfully.
screen shot 2016-10-20 at 11 17 09 pm

@leeight
Copy link
Contributor

leeight commented Oct 21, 2016

@lacker I think it's different. In the browser console you call fetch('aaa')) which was automatically converted to fetch('https://www.google.com/aaa'), the request url is valid. But in react-native, when we call fetch we should pass an specific valid url, but 'aaa' is invalid.

@lacker
Copy link
Contributor

lacker commented Dec 17, 2016

Ah, you are correct, when I call something invalid in the browser like fetch("https://https://").then(() => console.log('YES')).catch(() => console.log('NO')) then the promise does indeed reject.

@npomfret
Copy link
Contributor

This is still happening on RN0.39.2 on Android.

E/unknown:React: Exception in native call
                                                            java.lang.IllegalArgumentException: unexpected url: too/bar
                                                                at okhttp3.Request$Builder.url(Request.java:141)
                                                                at com.facebook.react.modules.network.NetworkingModule.sendRequest(NetworkingModule.java:168)
                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                at java.lang.reflect.Method.invoke(Method.java:372)
                                                                at com.facebook.react.bridge.BaseJavaModule$JavaMethod.invoke(BaseJavaModule.java:318)
                                                                at com.facebook.react.cxxbridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:158)
                                                                at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
                                                                at android.os.Handler.handleCallback(Handler.java:815)
                                                                at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
                                                                at android.os.Looper.loop(Looper.java:194)
                                                                at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:196)
                                                                at java.lang.Thread.run(Thread.java:818)

@satya164
Copy link
Contributor

@npomfret no one has worked on this. if you want to send a PR it'll be great.

@hramos hramos closed this as completed May 25, 2017
@hramos
Copy link
Contributor

hramos commented May 25, 2017

Closing this issue because it has been inactive for a while. If you think it should still be opened let us know why.

@hramos hramos added the Icebox label May 26, 2017
@MuneebJS
Copy link

MuneebJS commented Oct 20, 2017

Re-open it, please.

@laurent22
Copy link

Please re-open as this is still an issue in latest React Native.

This is especially an issue when doing a fetch() with a user-supplied URL. For example, someone set a URL to "https://ocloud. de/example" (notice the space) and that resulted in crashing the app with no error message in production, despite the fetch call being wrapped in a try/catch block.

Thankfully the user notice the extra space eventually but it's the kind of crash that could have taken a while to solve.

@hramos
Copy link
Contributor

hramos commented Jan 30, 2018

Is anyone working on a PR? The issue was closed after five months of inactivity. Seems like a straightforward fix (the promise should be rejected), if this is something that affects you.

@laurent22
Copy link

I've looked at it at some point, but was looking for a JavaScript fetch function where I wanted to add checks as suggested by @satya164, but there's no such JS function as it seems it's purely native. I don't really have the skills to fix the native side, but I might take another look.

@satya164
Copy link
Contributor

It's not native. fetch is a polyfill over XMLHttpRequest whose API is implemented in JavaScript over the native networking module.

jcurtis added a commit to jcurtis/react-native that referenced this issue Feb 26, 2018
…lid URL on Android

Currently if you invoke `fetch()` with an invalid URL ("aaa" for
example) you cannot catch the error in javascript since it's not
reported. Instead the entire app crashes.

Fixes facebook#7436 and facebook#18087

Hopefully.
@jcurtis
Copy link
Contributor

jcurtis commented Feb 26, 2018

I opened a PR that hopefully fixes this issue #18103

facebook-github-bot pushed a commit that referenced this issue Feb 27, 2018
…lid URL on Android

Summary:
Currently if you invoke `fetch()` with an invalid URL ("aaa" for
example) you cannot catch the error in javascript since it's not
reported. Instead the entire app crashes.

Fixes #7436 and #18087

Hopefully.

<!--
Thank you for sending the PR! We appreciate you spending the time to work on these changes.

Help us understand your motivation by explaining why you decided to make this change.

You can learn more about contributing to React Native here: http://facebook.github.io/react-native/docs/contributing.html

Happy contributing!

-->

Fix using fetch on Android with user generated input.

Added relevant unit test

`./scripts/run-android-local-unit-tests.sh` all pass

[ANDROID] [BUGFIX] [fetch] - Allow "unexpected url" exception to be caught on Android when using fetch
<!--
Help reviewers and the release process by writing your own release notes

**INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

  CATEGORY
[----------]        TYPE
[ CLI      ]   [-------------]      LOCATION
[ DOCS     ]   [ BREAKING    ]   [-------------]
[ GENERAL  ]   [ BUGFIX      ]   [-{Component}-]
[ INTERNAL ]   [ ENHANCEMENT ]   [ {File}      ]
[ IOS      ]   [ FEATURE     ]   [ {Directory} ]   |-----------|
[ ANDROID  ]   [ MINOR       ]   [ {Framework} ] - | {Message} |
[----------]   [-------------]   [-------------]   |-----------|

[CATEGORY] [TYPE] [LOCATION] - MESSAGE

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Closes #18103

Differential Revision: D7097110

Pulled By: hramos

fbshipit-source-id: 69144e8a0f7404d9bcc7c71a94650de36a48c84a
@anurag1018
Copy link

I am having the same issue in my application. It would be a huge help if someone could provide a code for the the promise rejection with fetch.

@laurent22
Copy link

In my case I've ended up wrapping fetch in my own function that does the URL validation:

const urlValidator = require('valid-url');

function myfetch(url, options = null) {
	const validatedUrl = urlValidator.isUri(url);
	if (!validatedUrl) throw new Error('Not a valid URL: ' + url);
	return fetch(validatedUrl, options);
}

@jcurtis
Copy link
Contributor

jcurtis commented Mar 12, 2018

@anurag1018 The issue has been fixed in #18103 we just need to wait for it to be released.

@facebook facebook locked as resolved and limited conversation to collaborators Jul 19, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests