反应本机fetch()网络请求失败


145

当我使用react-native init(RN版本0.29.1)创建一个全新的项目并将提取内容放入公共Facebook演示电影API的render方法中时,它将引发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);
      });

1
我不确定。我使用的是iOS仿真器,我认为它使用了计算机的互联网连接
Alek Hurst,2016年

尝试手动加载模拟器并在野生动物园中打开url
FuzzyTree 2016年

5
http- > https(如果可能)将最有可能解决您的问题
尼克·朱伯

1
我一直在使用IP 192.168.1.25:3000ifconfig而没有将服务器绑定到该IPrails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio

1
是的,我尝试了所有。对我没有任何帮助
Vigneswaran

Answers:


140

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

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

2
这个答案对我有用。对于React Native的其他新用户,也可以通过xcode编辑该文件(info.plist):stackoverflow.com/a/38219454/1299792
Marklar

86
android呢?我也在Android中面临同样的问题。
维杰·夏尔玛

16
究竟。有人有安卓的答案吗?
扎克·库克

1
当我将其放在ios / build / info.plist上并运行时:react-native run-ios ios / build / info.plist被覆盖并退出我的更改我该怎么办?
豪尔赫·万德·桑塔纳·乌雷尼亚

1
@JorgeWanderSantanaUreña修改[your_project_folder_name] / ios / [your_project_folder_name] /In‌fo.plist
kgosse

58

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

来源:在iOS 9和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>

27
android呢?
arisalexis

3
我的React Native应用程序的多个目录中似乎有多个info.plist文件。知道哪个文件夹包含要更改的正确文件吗?
Marklar '17

2
@Marklar [your_project_folder_name] / ios / [your_project_folder_name] /Info.plist
Stich

如果我在这里使用本地主机:<key> yourserver.com </ key>,准备好发布时,需要对其进行更改,对吗?
Anayo Oleru

36

我使用localhost的是地址,这显然是错误的。将其替换为服务器的IP地址(在仿真器所在的网络中)后,它可以正常工作。

编辑

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

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


4
谢谢。可能是我所见过的唯一适用于android的响应。使用了我的网络IP地址,它可以正常工作。例如http://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield '18

1
不要忘了“ http://”,否则它将无法正常工作……想知道为什么它可以在邮递员上使用,但不能用于提取
Moucheg 18'Jul

@Mahmoodvcs您的回答对我有很大帮助,非常感谢,我正在使用android模拟器。
佩纳·平达达

14

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

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

@JohhanSantana您可能可以查看原始图像数据并从一开始就获取它,但是react native拾取器只是为我返回了“图像”。
NickJ



7

我在Android上遇到了同样的问题,但设法找到了解决方案。由于默认情况下API级别为28,因此Android禁止明文流量(非https请求)。但是,react-native将网络安全配置添加到调试版本(android/app/src/debug/res/xml/react_native_config.xml),该版本定义了某些域(localhost和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>

这对我来说反应本机0.59和目标sdk 28 :)
sameera madushan

7

我在Android 9上遇到了同样的问题,因为出现了“ http”,并且通过在 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>


2
谢谢,这也为我工作。这是因为Android是不是在API支持28 HTTP了每默认
桂赫尔佐格

5

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

这应该起作用,并给您预期的响应。


我只需要执行步骤4即可工作。谢谢!
布鲁诺·塞拉诺


4

对于Android用户:

  1. 替换localhost,因为当您运行在Android设备上的项目,本地主机是指向Android设备s到局域网的IP地址,而不是你的电脑,例如:改变http://localosthttp://192.168.1.123

  2. 如果您的请求URL是HTTPS并且您的Android设备在代理下,则假定您在Android设备中安装了用户添加的CA(例如burp suite的CA或Charles的CA),请确保您的Android版本低于Nougat(7.0),因为:Android Nougat中对可信证书颁发机构的更改

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


3

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

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

即使我遇到该错误,我也已经做到了,还有其他解决方法吗?
masud_moni

@masud_moni您找到解决问题的方法吗?我仍然有同样的问题
拉斐尔·罗蒂罗蒂

@RafaelRotiroti是的,我已经解决了这个问题,但是尽管已经有一段时间了,但是很难记住,如果您使用了许可并且仍然遇到问题,请分享详细信息。我会尽力提供帮助,您也会请其他人研究一下
masud_moni

@masud_moni谢谢,我已经使用运行ifconfig命令后提供的ip修复了该问题。AVD创建了一个虚拟设备,因此使用与虚拟机相同的理论,即设备中127.0.0.1中没有托管任何虚拟设备。所以我使用192.168.xx IP,一切也都很好
拉斐尔·罗蒂罗蒂

2

我有类似的问题。以我为例,对localhost的请求正在工作,突然停止。原来,问题是我关闭了Android手机上的wifi。


2

这对我有用,android使用特殊类型的IP地址10.0.2.2然后是端口号

import { Platform } from 'react-native';

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

1

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


1

您应该在.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;
});

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

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


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,
      });
    });

-1

只是您有获取中的更改...。

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);
     });

-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在您的react-native fetch(调用中使用。


-1

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

您能详细说明一下吗?我很好奇它是如何工作的?
ganeshdeshmukh

修改了评论,希望对您有所帮助
xyz

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.