Javascript React Native fetch()网络请求失败
当我使用Javascript React Native fetch()网络请求失败,javascript,react-native,fetch-api,Javascript,React Native,Fetch Api,当我使用react native init(RN版本0.29.1)创建一个全新的项目,并在呈现方法中将一个fetch放入公共facebook演示电影API时,它抛出一个网络请求失败。有一个非常无用的堆栈跟踪,我无法在chrome控制台中调试网络请求。这是我要发送的回执: fetch('http://facebook.github.io/react-native/movies.json') .then((response) => response.json()) .t
react native init
(RN版本0.29.1)创建一个全新的项目,并在呈现方法中将一个fetch放入公共facebook演示电影API时,它抛出一个网络请求失败
。有一个非常无用的堆栈跟踪,我无法在chrome控制台中调试网络请求。这是我要发送的回执:
fetch('http://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
这里的问题是,iOS默认情况下不允许HTTP请求,只允许HTTPS。如果要启用HTTP请求,请将其添加到
info.plist
:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
NSAppTransportSecurity
NSAllowsArbitraryLoads
不建议允许http的所有域。
仅对必要的域进行例外
资料来源:
将以下内容添加到应用程序的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>
NSAppTransportSecurity
NSExceptionDomains
yourserver.com
n包括多个域
NSTemporary ExceptionalLowsInSecureHttpLoads
NSTemporaryExceptionMinimumTLSVersion
TLSv1.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);
});
React Native Docs对此给出了答案 苹果已阻止隐式明文HTTP资源加载。因此,我们需要添加以下项目的Info.plist(或等效)文件
NSAppTransportSecurity
NSExceptionDomains
本地服务器
NSTemporary ExceptionalLowsInSecureHttpLoads
对于Android,您可能没有在AndroidManifest.xml中添加权限 需要添加以下权限
<uses-permission android:name="android.permission.INTERNET" />
问题可能出在服务器配置中 安卓7.0有一个bug。Vicky Chijwani提出的解决方案: 将服务器配置为使用椭圆曲线prime256v1。对于 例如,在nginx1.10中,可以通过设置ssl\u ecdh\u曲线来实现这一点 prime256v1
我使用了
localhost
作为地址,这显然是错误的。在用服务器的IP地址(在emulator所在的网络中)替换它之后,它工作得非常好
编辑
在Android Emulator中,开发机器的地址是10.0.2.2
。更多解释
对于Genymotion,地址是10.0.3.2
。更多信息我也有类似的问题。
在我的例子中,对localhost的请求正在工作,并突然停止。
原来问题是我在android手机上关闭了wifi。我在android手机上遇到了这个问题- URL-localhost/authToken.json-不起作用:( URL-10.106.105.103/authToken.json-不起作用:( URL--已工作:):D
注意-在Linux上使用
ifconfig
,或在Windows上使用ipconfig
来查找计算机IpAddress对我们来说,这是因为我们上载了一个文件,而RN文件选择器没有给出正确的mime类型。它只给了我们“image”作为类型。我们需要将其更改为“image/jpg”以使提取工作
form.append(uploadFileName, {
uri : localImage.full,
type: 'image/jpeg',
name: uploadFileName
})
对于Android用户:
localhost
s替换为Lan IP地址,因为在Android设备上运行项目时,localhost指向的是Android设备,而不是您的计算机,例如:changehttp://localost
至http://192.168.1.123
保护所有应用程序数据是 Android应用程序沙箱。Android牛轧糖改变了应用程序的运行方式 与用户和管理员提供的CA交互。默认情况下,应用程序 除非应用程序 显式选择。默认情况下,此安全设置会减少应用程序 攻击表面并鼓励一致处理网络和 基于文件的应用程序数据
对于Android设备,请转到项目根文件夹并运行以下命令:
adb reverse tcp:[your_own_server_port] tcp:[your_own_server_port]
e、 例如,adb反向tcp:8088 tcp:8088
这将使您的物理设备(即Android手机)在address上侦听在您的开发机器(即您的计算机)上运行的localhost服务器
之后,您可以在react native
fetch(
)调用中直接使用http:localhost:[your_port]/your_api。这对我很有效,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/';
如果您将docker用于RESTAPI,我的一个工作案例是替换主机名:
http://demo.test/api
机器ip地址:http://x.x.x.x/api
。您可以通过检查无线网络上的ipv4来获取IP。您还应该打开手机的wifi。我在Android上也遇到了同样的问题,但是我设法找到了解决方案。默认情况下,Android从API级别28开始阻止明文通信(非https请求)。但是,react-native在调试版本中添加了一个网络安全配置(Android/app/src/debug/res/xml/react-native\u-config.xml
),该版本定义了一些域(本地主机和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>
本地服务器
10.0.2.2
10.0.3.2
本地开发人员
我在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) 我使用此方法添加了URL的有效证书->步骤2
http://lpains.net/articles/2018/install-root-ca-in-android/
此证书将添加到“用户”选项卡
4) 将属性android:networkSecurityConfig
添加到
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="user"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
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;
});
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
<?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>
<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>
headers: {
Authorization: token,
'Content-type': 'application/json',
/** rest of headers... */
}