React Native fetch()网络请求失败

时间:2016-07-17 07:42:43

标签: javascript react-native fetch

当我使用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);
      });

29 个答案:

答案 0 :(得分:129)

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

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

答案 1 :(得分:53)

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

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

将以下内容添加到应用的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>

答案 2 :(得分:16)

我使用localhost作为地址,这显然是错误的。在用服务器的IP地址(在模拟器所在的网络中)替换之后,它完美地运行了。

修改

在Android Emulator中,开发计算机的地址为10.0.2.2。更多解释here

对于Genymotion,地址为10.0.3.2。更多信息here

答案 3 :(得分:8)

React Native Docs为此提供了答案。

  

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

答案 4 :(得分:7)

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

Android 7.0有一个错误described here。 Vicky Chijwani提出的解决方法:

  

将服务器配置为使用椭圆曲线prime256v1。对于   例如,在Nginx 1.10中,您可以通过设置ssl_ecdh_curve来完成此操作   prime256v1;

答案 5 :(得分:6)

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

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

答案 6 :(得分:3)

如果您使用 localhost 只需更改它:

来自:http://localhost:3030 :http://10.0.2.2:3030

答案 7 :(得分:3)

我在Android上遇到了同样的问题,但设法找到了解决方案。由于默认情况下API级别为28,因此Android禁止明文流量(非https请求)。但是,react-native将网络安全配置添加到调试版本(NavigationCacheMode),该版本定义了某些域(localhost和AVD / Genymotion的主机IP),可以在开发模式下不使用SSL的情况下使用。 您可以在其中添加域以允许http请求。

Required

答案 8 :(得分:2)

对于Android,您可能错过了在AndroidManifest.xml中添加权限 需要添加以下权限。

<uses-permission android:name="android.permission.INTERNET" /> 

答案 9 :(得分:2)

我有类似的问题。 在我的情况下,对localhost的请求正在工作并突然停止。 事实证明问题是我在我的Android手机上关闭了我的wifi。

答案 10 :(得分:2)

我在Android上遇到此问题-

URL- localhost / authToken.json-不起作用:(

URL- 10.106.105.103/authToken.json-不起作用:(

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

注意-在Linux上使用ifconfig或在Windows上使用ipconfig查找计算机IpAddress

答案 11 :(得分:2)

通过在0.0.0.0上运行模拟服务器
注意:当您使用json-server运行另一台服务器时,此功能可在Expo上使用。


另一种方法是在0.0.0.0而不是localhost或127.0.0.1上运行模拟服务器。

这使得模拟服务器可以在LAN上访问,并且因为Expo要求开发机器和运行Expo应用程序的移动设备位于同一网络上,所以模拟服务器也可以访问。

使用json-server时,可以使用以下命令来实现

json-server --host 0.0.0.0 --port 8000 ./db.json --watch

访问此link以获得更多信息。

答案 12 :(得分:2)

对于Android用户:

  1. localhost替换为Lan IP地址,因为在Android设备上运行项目时,本地主机指向Android设备而不是计算机,例如:更改http://localosthttp://192.168.1.123

  2. 如果您的请求URL是HTTPS,并且您的Android设备位于代理服务器下,请假定您在Android设备中安装了用户添加的CA(例如burp suite的CA或Charles的CA),请确保您的Android版本低于牛轧糖(7.0),因为:Changes to Trusted Certificate Authorities in Android Nougat
      

    用户添加的CA
      保护所有应用程序数据是其主要目标   Android应用程序沙箱。 Android Nougat改变了应用程序的方式   与用户和管理员提供的CA进行交互。默认情况下,   目标API级别24(通过设计)将不接受此类CA,除非该应用   明确选择加入。此默认安全设置会减少应用程序   攻击面并鼓励对网络的一致处理   基于文件的应用程序数据。

答案 13 :(得分:1)

如果您将docker用于REST api,对我来说,一个可行的例子是将主机名http://demo.test/api替换为机器ip地址:http://x.x.x.x/api。您可以通过检查无线网络上的ipv4来获取IP。您还应该从手机上获得wifi。

答案 14 :(得分:1)

  1. 在AndroidManifest.xml中添加android:usesCleartextTraffic="true"行。

  2. 从您的android文件夹中删除所有调试文件夹。

答案 15 :(得分:1)

由于“ http”,我在Android 9上遇到了同样的问题,并且通过在其中添加 android:usesCleartextTraffic =“ true” 解决了该问题 AndroidManifest.xml

<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>

答案 16 :(得分:1)

This worked for me, android uses a special type of IP address 10.0.2.2 then port number

import { Platform } from 'react-native';

export const baseUrl = Platform.OS === 'android' ?
    'http://10.0.2.2:3000/'
: 
'http://localhost:3000/';

答案 17 :(得分:0)

我在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)为了找出日志中的确切错误,我首先在应用上使用Cmd + M启用了“远程调试JS”

2)报告的错误是

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

3)我使用此方法->步骤2

添加了URL的有效证书。
http://lpains.net/articles/2018/install-root-ca-in-android/

此证书已添加到“用户”选项卡。

4)将属性android:networkSecurityConfig属性添加到AndroidManifest.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>

这应该可以工作,并给您期望的答复。

答案 18 :(得分:0)

您应该在.then中处理错误情况以获取API。

例如:

fetch(authURl,{ method: 'GET'})
.then((response) => {      
  const statusCode = response.status;
  console.warn('status Code',statusCode);
  if(statusCode==200){
    //success code
  }else{
    //handle other error code
  }      
},(err) => {
  console.warn('error',err)
})
.catch((error) => {
  console.error(error);
  return error;
});

答案 19 :(得分:0)

对于android,将android:networkSecurityConfig =“ @ xml / network_security_config”添加到AndroidManifest.xml中的应用程序标签,如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ... >
        <application android:networkSecurityConfig="@xml/network_security_config"
                        ... >
            ...
        </application>
    </manifest>

network_security_config.xml文件内容:

<?xml version='1.0' encoding='utf-8'?>
<network-security-config>
<debug-overrides>
    <trust-anchors>
        <!-- Trust user added CAs while debuggable only -->
        <certificates src="user" />
    </trust-anchors>
</debug-overrides>

<!-- let application to use http request -->
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

答案 20 :(得分:0)

您可以使用以下方法处理它:

catch((error) => {
      this.setState({
        typing_animation_button: false,
      });
      console.log(error);
      if ('Timeout' || 'Network request failed') {
        toast_show = true;
        toast_type = 'error';
        toast_text = 'Network failure';
      }
      this.setState({
        disable_button: false,
      });
    });

答案 21 :(得分:0)

这不是答案,而是选项。 我切换到https://github.com/joltup/rn-fetch-blob 对于表单数据和文件都很好

答案 22 :(得分:0)

解决方案是简单更新nodejs版本14或更高版本

答案 23 :(得分:0)

就我而言,Android仿真器未连接到Wi-Fi。

在此处查看Android Studio - Android Emulator Wifi Connected with No Internet

答案 24 :(得分:0)

在我的情况下,我有 https url,但获取返回网络请求失败错误,所以我只是将正文字符串化,它的工作很有趣

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue'
  })
});

答案 25 :(得分:0)

只是你有获取变化....

fetch('http://facebook.github.io/react-native/movies.json')
    .then((response) => response.json())
    .then((responseJson) => {
        /*return responseJson.movies; */
        alert("result:"+JSON.stringify(responseJson))
        this.setState({
            dataSource:this.state.dataSource.cloneWithRows(responseJson)
        })
     }).catch((error) => {
         console.error(error);
     });

答案 26 :(得分:0)

对我来说......我已经有https......一旦我将'Content-type': 'application/json'添加到headers

后问题就消失了
headers: {
  Authorization: token,
  'Content-type': 'application/json',
  /** rest of headers... */
}

平台:安卓

答案 27 :(得分:-1)

对于Android设备,请转到您的项目根文件夹并运行以下命令:

adb reverse tcp:[your_own_server_port] tcp:[your_own_server_port]

例如adb reverse tcp:8088 tcp:8088

这将使您的物理设备(即Android手机)监听地址为http://localhost:[your_own_server_port]的开发计算机(即计算机)上运行的localhost服务器。

此后,您可以在本机http:localhost:[your_port] /your_api)调用中直接使用fetch(

答案 28 :(得分:-3)

示例:

return fetch('http://<your ip>')
  .then((response) => response.json())
  .then((responseJson) => {
    console.log(responseJson)
  })
  .catch((error) => {
    console.error(error);
  });