Javascript React Native fetch() 网络请求失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38418998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:28:30  来源:igfitidea点击:

React Native fetch() Network Request Failed

javascriptreact-nativefetch-api

提问by Alek Hurst

When I create a brand new project using react-native init(RN version 0.29.1) and put a fetch in the render method to the public facebook demo movie API, it throws a Network Request Failed. There is a very useless stack trace and I can't debug network requests in the chrome console. Here is the fetch I'm sending:

当我使用react-native init(RN 版本 0.29.1)创建一个全新的项目并将渲染方法中的提取放入公共 facebook 演示电影 API 时,它会抛出一个Network Request Failed. 有一个非常无用的堆栈跟踪,我无法在 Chrome 控制台中调试网络请求。这是我发送的提取:

fetch('http://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.movies;
      })
      .catch((error) => {
        console.error(error);
      });

采纳答案by Alek Hurst

The problem here is that iOS does not allow HTTP requests by default, only HTTPS. If you want to enable HTTP requests add this to your info.plist:

这里的问题是 iOS 默认不允许 HTTP 请求,只允许 HTTPS。如果要启用 HTTP 请求,请将其添加到您的info.plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

回答by Lavi Avigdor

Not recommended to allow all domains for http. Make an exception for just the necessary domains.

不建议允许所有域都使用 http。仅对必要的域进行例外处理。

Source: Configuring App Transport Security Exceptions in iOS 9 and OSX 10.11

来源:在 iOS 9 和 OSX 10.11 中配置应用传输安全例外

Add the following to the info.plist file of your app:

将以下内容添加到您应用的 info.plist 文件中:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

回答by Mahmoodvcs

I was using localhostfor the address, which was obviously wrong. After replacing it with the IP address of the server (in the network that emulator is), it worked perfectly.

我用localhost的地址,这显然是错误的。将其替换为服务器的 IP 地址(在模拟器所在的网络中)后,它运行良好。

Edit

编辑

In Android Emulator, the address of the development machine is 10.0.2.2. More explanation here

在 Android Emulator 中,开发机的地址是10.0.2.2. 更多解释在这里

For Genymotion, the address is 10.0.3.2. More info here

对于 Genymotion,地址是10.0.3.2。更多信息在这里

回答by NickJ

For us it was because we were uploading a file and the RN filePicker did not give the proper mime type. It just gave us 'image' as the type. We needed to change it to 'image/jpg' to get the fetch to work.

对我们来说,这是因为我们正在上传一个文件,而 RN filePicker 没有提供正确的 mime 类型。它只是给了我们“图像”作为类型。我们需要将其更改为 'image/jpg' 以使提取工作。

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })

回答by ocean

React Native Docs gives the answer for this.

React Native Docs 给出了答案。

Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's Info.plist (or equivalent) file.

Apple 已阻止隐式明文 HTTP 资源加载。所以我们需要在我们项目的 Info.plist(或等效的)文件中添加以下内容。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

React Native Docs -> Integration With Existing Apps -> Test your integration -> Add App Transport Security exception

React Native Docs -> 与现有应用程序集成 -> 测试您的集成 -> 添加应用程序传输安全例外

回答by Dmitry Maksakov

The problem may be in server configuration.

问题可能出在服务器配置中。

Android 7.0 has a bug described here. Workaround proposed by Vicky Chijwani:

Android 7.0 有此处描述的错误。Vicky Chijwani 提出的解决方法:

Configure your server to use the elliptic curve prime256v1. For example, in Nginx 1.10 you do this by setting ssl_ecdh_curve prime256v1;

配置您的服务器以使用椭圆曲线 prime256v1。例如,在 Nginx 1.10 中,您可以通过设置 ssl_ecdh_curve prime256v1 来做到这一点;

回答by Johannes Spohr

I got the same issue on Android but I managed to find a solution for it. Android is blocking cleartext traffic (non-https-requests) since API Level 28 by default. However, react-native adds a network-security-config to the debug version (android/app/src/debug/res/xml/react_native_config.xml) which defines some domains (localhost, and the host IPs for AVD / Genymotion), which can be used without SSL in dev mode. You can add your domain there to allow http requests.

我在 Android 上遇到了同样的问题,但我设法找到了解决方案。自 API 级别 28 默认情况下,Android 会阻止明文流量(非 https 请求)。但是,react-native 在调试版本 ( android/app/src/debug/res/xml/react_native_config.xml) 中添加了一个 network-security-config ,它定义了一些域(本地主机,以及 AVD / Genymotion 的主机 IP),可以在开发模式下不使用 SSL 使用。您可以在那里添加您的域以允许 http 请求。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="false">localhost</domain>
    <domain includeSubdomains="false">10.0.2.2</domain>
    <domain includeSubdomains="false">10.0.3.2</domain>
    <domain includeSubdomains="true">dev.local</domain>
  </domain-config>
</network-security-config>

回答by henryoats

I came across the same issue on Android Emulator, where I tried to access an external HTTPS URL with a valid certificate. But fetching that URL in react-native failed

我在 Android Emulator 上遇到了同样的问题,我尝试使用有效证书访问外部 HTTPS URL。但是在 react-native 中获取那个 URL 失败了

'fetch error:', { [TypeError: Network request failed]
sourceURL: 'http://10.0.2.2:8081/index.delta?platform=android&dev=true&minify=false' }

1) To find out the exact error in the logs, I first enabled 'Debug JS Remotely' using Cmd + M on the app

1)为了找出日志中的确切错误,我首先在应用程序上使用 Cmd + M 启用了“远程调试 JS”

2) The error reported was

2)报告的错误是

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

3) I added the URL's valid certificate using this method -> STEP 2

3) 我使用这种方法添加了 URL 的有效证书 -> STEP 2

http://lpains.net/articles/2018/install-root-ca-in-android/

This certificate gets added to the User tab.

该证书被添加到用户选项卡中。

4) Add the attribute android:networkSecurityConfigattribute to AndroidManifest.xml

4)在android:networkSecurityConfigAndroidManifest.xml中添加attribute属性

Add a Network Security Configuration file res/xml/network_security_config.xml:

添加网络安全配置文件 res/xml/network_security_config.xml:

<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="user"/>
            <certificates src="system"/>
        </trust-anchors>
    </base-config>
</network-security-config>

This should work and give you an expected response.

这应该可以工作并为您提供预期的响应。

回答by kautikmistry

I got the same issue on Android 9 because of the "http" and issue resolved by just adding android:usesCleartextTraffic="true"in AndroidManifest.xml

由于“http”,我在 Android 9 上遇到了同样的问题,只需在 AndroidManifest.xml 中添加android:usesCleartextTraffic="true" 即可解决问题

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
  android:usesCleartextTraffic="true"
 .......>
 .......
</application>

回答by Varun Kumar

I was having this problem for Android-

我在 Android 上遇到了这个问题-

URL- localhost/authToken.json - didn't work :(

URL- localhost/authToken.json - 没有用 :(

URL- 10.106.105.103/authToken.json - didn't work :(

URL- 10.106.105.103/authToken.json - 没有用 :(

URL- http://10.106.105.103/authToken.json- worked :) :D

URL- http://10.106.105.103/authToken.json- 工作 :) :D

Note- Use ifconfigon Linux or ipconfigon Windows to find machine IpAddress

注意 -ifconfig在 Linux 或ipconfigWindows 上使用以查找机器 IpAddress