React Native fetch() 网络请求失败
React Native fetch() Network Request Failed
当我使用 react-native init
(RN 版本 0.29.1)创建一个全新的项目并将提取方法放入 public 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);
});
这里的问题是iOS默认不允许HTTP请求,只允许HTTPS。如果您想启用 HTTP 请求,请将此添加到您的 info.plist
:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
不建议允许所有域用于 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>
只是你在 Fetch 中有变化....
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 给出了答案。
Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's Info.plist (or equivalent) file.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
对于 Android,您可能错过了在 AndroidManifest.xml 中添加权限
需要添加以下权限。
<uses-permission android:name="android.permission.INTERNET" />
问题可能出在服务器配置上。
Android 7.0 有一个错误 described here。 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;
我在地址中使用 localhost
,这显然是错误的。将其替换为服务器的 IP 地址(在模拟器所在的网络中)后,它完美运行。
编辑
在AndroidEmulator中,开发机地址为10.0.2.2
。更多解释 here
对于 Genymotion,地址是 10.0.3.2
。更多信息 here
我有类似的问题。
在我的例子中,对 localhost 的请求正在工作,但突然停止了。
原来问题是我关闭了 android phone.
上的 wifi
我在 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
对我们来说,这是因为我们正在上传文件,而 RN filePicker 没有提供正确的 mime 类型。它只是给了我们 'image' 作为类型。我们需要将其更改为 'image/jpg' 才能使提取正常工作。
form.append(uploadFileName, {
uri : localImage.full,
type: 'image/jpeg',
name: uploadFileName
})
Android 用户:
将 localhost
s 替换为局域网 IP 地址,因为当您 运行 项目在 Android 设备上时,localhost 指向 Android 设备,而不是您的计算机,例如:将 http://localost
更改为 http://192.168.1.123
- 如果你的请求 URL 是 HTTPS 并且你的 Android 设备在代理下,假设你已经在你的 Android 设备,请确保您的 Android 版本低于 Nougat(7.0),因为:AndroidNougat 中受信任证书颁发机构的更改
User-added CAs
Protection of all application data is a key goal of the
Android application sandbox. Android Nougat changes how applications
interact with user- and admin-supplied CAs. By default, apps that
target API level 24 will—by design—not honor such CAs unless the app
explicitly opts in. This safe-by-default setting reduces application
attack surface and encourages consistent handling of network and
file-based application data.
对于 Android 设备,转到项目根文件夹并 运行 命令:
adb reverse tcp:[your_own_server_port] tcp:[your_own_server_port]
例如,adb reverse tcp:8088 tcp:8088
这将使您的物理设备(即 Android phone)在您的开发计算机(即您的计算机)地址 http://localhost:[your_own_server_port] 上侦听本地主机服务器 运行ning ].
之后,你可以直接在你的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 用于 REST api,我的一个工作案例是将主机名:http://demo.test/api
替换为机器 IP 地址:http://x.x.x.x/api
。您可以通过检查无线网络上的 ipv4 来获取 IP。你应该也有从 phone 开始的 wifi。
我在 Android 上遇到了同样的问题,但我设法找到了解决方案。 Android 自 API 级别 28 默认情况下阻止明文流量(非 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>
我在 Android 模拟器上遇到了同样的问题,我在其中尝试使用有效证书访问外部 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 启用 'Debug JS Remotely'
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
属性到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>
这应该会起作用并给您一个预期的响应。
您应该在 .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;
});
对于 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>
由于 "http",我在 Android 9 上遇到了同样的问题,只需添加 android:usesCleartextTraffic="true"[ 即可解决问题=19=]在
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>
在AndroidManifest.xml中添加android:usesCleartextTraffic="true"
行。
从您的 android 文件夹中删除所有调试文件夹。
通过 运行在 0.0.0.0 上设置 mock-server
注意:当您使用 json-server.
运行 连接另一台服务器时,这在 Expo 上有效
另一种方法是 运行 0.0.0.0 上的模拟服务器,而不是本地主机或 127.0.0.1。
这使得模拟服务器可以在 LAN 上访问,并且因为 Expo 需要开发机器和移动 运行将 Expo 应用程序连接到同一网络上,模拟服务器也可以访问。
使用json-server
时可以通过以下命令实现
json-server --host 0.0.0.0 --port 8000 ./db.json --watch
访问此 link 了解更多信息。
这不是答案,而是选项。
我切换到 https://github.com/joltup/rn-fetch-blob
它适用于 form-data 和文件
解决方法是简单更新 nodejs 版本 14 或更高
在我的例子中,Android 模拟器没有连接到 Wi-Fi。
看这里
在我的例子中,我有 https url 但是获取 return 网络请求失败错误所以我只是将正文字符串化并且它工作起来很有趣
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue'
})
});
如果您使用本地主机,只需更改它:
来自 :http://localhost:3030
至:http://10.0.2.2:3030
对我来说...我已经 https
...我将 'Content-type': 'application/json'
添加到 headers
后问题就消失了
headers: {
Authorization: token,
'Content-type': 'application/json',
/** rest of headers... */
}
平台: Android
HTTP
不再被允许。请使用HTTPS
从 Android API 28 和 iOS 9 开始,这些平台默认禁用不安全的 HTTP 连接。
"dependencies": {"react": "17.0.2","react-native": "0.66.1"},
我在使用 Android 模拟器 .
时遇到了这个问题
在AndroidManifest.xml
里面加入这几行代码
<application
....
....
android:usesCleartextTraffic="true">
然后,尝试运行你的代码在一个真正的物理设备,而不是模拟器,
在物理设备上 运行 - 连接你的 USB 并尝试 运行 npx react-native 运行-android
只需添加
<uses-permission android:name="android.permission.INTERNET" />
<application
android:usesCleartextTraffic="true"
在您的 AndroidManifest.xml 中,然后将 fetch URL 域 (localhost) 替换为您的 IP 地址,
const dataRaw = await fetch('http://192.168.8.102:4000');
就我而言,https
请求也显示相同。
重新安装应用程序解决了。
当我使用 react-native init
(RN 版本 0.29.1)创建一个全新的项目并将提取方法放入 public 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);
});
这里的问题是iOS默认不允许HTTP请求,只允许HTTPS。如果您想启用 HTTP 请求,请将此添加到您的 info.plist
:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
不建议允许所有域用于 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>
只是你在 Fetch 中有变化....
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 给出了答案。
Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's Info.plist (or equivalent) file.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
对于 Android,您可能错过了在 AndroidManifest.xml 中添加权限 需要添加以下权限。
<uses-permission android:name="android.permission.INTERNET" />
问题可能出在服务器配置上。
Android 7.0 有一个错误 described here。 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;
我在地址中使用 localhost
,这显然是错误的。将其替换为服务器的 IP 地址(在模拟器所在的网络中)后,它完美运行。
编辑
在AndroidEmulator中,开发机地址为10.0.2.2
。更多解释 here
对于 Genymotion,地址是 10.0.3.2
。更多信息 here
我有类似的问题。 在我的例子中,对 localhost 的请求正在工作,但突然停止了。 原来问题是我关闭了 android phone.
上的 wifi我在 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
对我们来说,这是因为我们正在上传文件,而 RN filePicker 没有提供正确的 mime 类型。它只是给了我们 'image' 作为类型。我们需要将其更改为 'image/jpg' 才能使提取正常工作。
form.append(uploadFileName, {
uri : localImage.full,
type: 'image/jpeg',
name: uploadFileName
})
Android 用户:
将
localhost
s 替换为局域网 IP 地址,因为当您 运行 项目在 Android 设备上时,localhost 指向 Android 设备,而不是您的计算机,例如:将http://localost
更改为http://192.168.1.123
- 如果你的请求 URL 是 HTTPS 并且你的 Android 设备在代理下,假设你已经在你的 Android 设备,请确保您的 Android 版本低于 Nougat(7.0),因为:AndroidNougat 中受信任证书颁发机构的更改
User-added CAs
Protection of all application data is a key goal of the Android application sandbox. Android Nougat changes how applications interact with user- and admin-supplied CAs. By default, apps that target API level 24 will—by design—not honor such CAs unless the app explicitly opts in. This safe-by-default setting reduces application attack surface and encourages consistent handling of network and file-based application data.
对于 Android 设备,转到项目根文件夹并 运行 命令:
adb reverse tcp:[your_own_server_port] tcp:[your_own_server_port]
例如,adb reverse tcp:8088 tcp:8088
这将使您的物理设备(即 Android phone)在您的开发计算机(即您的计算机)地址 http://localhost:[your_own_server_port] 上侦听本地主机服务器 运行ning ].
之后,你可以直接在你的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 用于 REST api,我的一个工作案例是将主机名:http://demo.test/api
替换为机器 IP 地址:http://x.x.x.x/api
。您可以通过检查无线网络上的 ipv4 来获取 IP。你应该也有从 phone 开始的 wifi。
我在 Android 上遇到了同样的问题,但我设法找到了解决方案。 Android 自 API 级别 28 默认情况下阻止明文流量(非 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>
我在 Android 模拟器上遇到了同样的问题,我在其中尝试使用有效证书访问外部 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 启用 'Debug JS Remotely'
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
属性到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>
这应该会起作用并给您一个预期的响应。
您应该在 .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;
});
对于 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>
由于 "http",我在 Android 9 上遇到了同样的问题,只需添加 android:usesCleartextTraffic="true"[ 即可解决问题=19=]在 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>
在AndroidManifest.xml中添加
android:usesCleartextTraffic="true"
行。从您的 android 文件夹中删除所有调试文件夹。
通过 运行在 0.0.0.0 上设置 mock-server
注意:当您使用 json-server.
另一种方法是 运行 0.0.0.0 上的模拟服务器,而不是本地主机或 127.0.0.1。
这使得模拟服务器可以在 LAN 上访问,并且因为 Expo 需要开发机器和移动 运行将 Expo 应用程序连接到同一网络上,模拟服务器也可以访问。
使用json-server
时可以通过以下命令实现json-server --host 0.0.0.0 --port 8000 ./db.json --watch
访问此 link 了解更多信息。
这不是答案,而是选项。 我切换到 https://github.com/joltup/rn-fetch-blob 它适用于 form-data 和文件
解决方法是简单更新 nodejs 版本 14 或更高
在我的例子中,Android 模拟器没有连接到 Wi-Fi。
看这里
在我的例子中,我有 https url 但是获取 return 网络请求失败错误所以我只是将正文字符串化并且它工作起来很有趣
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue'
})
});
如果您使用本地主机,只需更改它:
来自 :http://localhost:3030
至:http://10.0.2.2:3030
对我来说...我已经 https
...我将 'Content-type': 'application/json'
添加到 headers
headers: {
Authorization: token,
'Content-type': 'application/json',
/** rest of headers... */
}
平台: Android
HTTP
不再被允许。请使用HTTPS
从 Android API 28 和 iOS 9 开始,这些平台默认禁用不安全的 HTTP 连接。
"dependencies": {"react": "17.0.2","react-native": "0.66.1"},
我在使用 Android 模拟器 .
在AndroidManifest.xml
里面加入这几行代码<application .... .... android:usesCleartextTraffic="true">
然后,尝试运行你的代码在一个真正的物理设备,而不是模拟器,
在物理设备上 运行 - 连接你的 USB 并尝试 运行 npx react-native 运行-android
只需添加
<uses-permission android:name="android.permission.INTERNET" />
<application
android:usesCleartextTraffic="true"
在您的 AndroidManifest.xml 中,然后将 fetch URL 域 (localhost) 替换为您的 IP 地址,
const dataRaw = await fetch('http://192.168.8.102:4000');
就我而言,https
请求也显示相同。
重新安装应用程序解决了。