![](/img/trans.png)
[英]React native TypeError: Network request failed with fetch()
[英]React Native fetch() Network Request Failed
当我使用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);
});
这里的问题是iOS默认不允许HTTP请求,只允许HTTPS。 如果您想启用 HTTP 请求,请将其添加到您的info.plist
:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
不建议允许所有域用于 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>
由于“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>
对我们来说,这是因为我们正在上传一个文件,而 RN filePicker 没有给出正确的 mime 类型。 它只是给了我们“图像”作为类型。 我们需要将其更改为“image/jpg”以使获取工作。
form.append(uploadFileName, {
uri : localImage.full,
type: 'image/jpeg',
name: uploadFileName
})
我在 Android 上遇到了同样的问题,但我设法找到了解决方案。 默认情况下,自 API 级别 28 以来,Android 会阻止明文流量(非 https 请求)。 但是,react-native 将 network-security-config 添加到调试版本( 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>
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>
安卓用户:
将localhost
替换为局域网 IP 地址,因为当您在 Android 设备上运行项目时,localhost 指向的是 Android 设备,而不是您的计算机,例如:将http://localost
更改为http://192.168.1.123
用户添加的 CA
保护所有应用程序数据是 Android 应用程序沙箱的一个关键目标。 Android Nougat 改变了应用程序与用户和管理员提供的 CA 交互的方式。 默认情况下,以 API 级别 24 为目标的应用程序在设计上不会支持此类 CA,除非应用程序明确选择加入。这种默认安全设置减少了应用程序的攻击面,并鼓励对网络和基于文件的应用程序数据进行一致处理。
问题可能出在服务器配置中。
Android 7.0 在此处描述了一个错误。 Vicky Chijwani 提出的解决方法:
将您的服务器配置为使用椭圆曲线 prime256v1。 例如,在 Nginx 1.10 中,您可以通过设置 ssl_ecdh_curve prime256v1;
我在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
如果您使用 localhost 只需更改它:
从: http://localhost:3030
到:http: http://10.0.2.2:3030
:3030
我在 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 的有效证书 -> STEP 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>
这应该可以工作并给您预期的响应。
对于Android,你可能错过了在AndroidManifest.xml中添加权限需要添加以下权限。
<uses-permission android:name="android.permission.INTERNET" />
我有类似的问题。 在我的情况下,对 localhost 的请求正在工作并突然停止。 事实证明,问题在于我在我的安卓手机上关闭了我的 wifi。
这对我有用,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://xxxx/api
。 您可以通过检查无线网络上的 ipv4 来获取 IP。 你也应该有手机上的wifi。
您应该在 .then 中处理 fetch 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.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
访问此链接了解更多信息。
在我的情况下,我有 https url 但获取返回网络请求失败错误,所以我只是对正文进行字符串化,它的工作很有趣
fetch('https://mywebsite.com/endpoint/', { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ firstParam: 'yourValue', secondParam: 'yourOtherValue' }) });
对我来说......我已经有https
......一旦我将'Content-type': 'application/json'
添加到headers
中,问题就消失了
headers: {
Authorization: token,
'Content-type': 'application/json',
/** rest of headers... */
}
平台:安卓
不再允许HTTP
。 请使用HTTPS
从 Android API 28 和 iOS 9 开始,这些平台默认禁用不安全的 HTTP 连接。
只需添加
<uses-permission android:name="android.permission.INTERNET" />
<application
android:usesCleartextTraffic="true"
在您的 AndroidManifest.xml 中,然后将 fetch URL domain (localhost)替换为您的 IP 地址,
const dataRaw = await fetch('http://192.168.8.102:4000');
在我的情况下,它对https
请求也显示相同。
重新安装应用程序解决了它。
在 AndroidManifest.xml 中添加android:usesCleartextTraffic="true"
行。
从您的 android 文件夹中删除所有调试文件夹。
这不是答案,而是选项。 我切换到https://github.com/joltup/rn-fetch-blob它适用于表单数据和文件
解决方法是简单更新nodejs版本14或更高
"dependencies": {"react": "17.0.2","react-native": "0.66.1"},
我在Android 模拟器上遇到了这个问题。
在 AndroidManifest.xml 中添加这些代码行
<application .... .... android:usesCleartextTraffic="true">
然后,尝试在真实的物理设备而不是模拟器中运行您的代码,
在物理设备上运行 - 连接你的 USB 并尝试运行 npx react-native run-android
TypeError: Network request failed
在 react-native 0.63.2(我正在测试)或更高版本中,如果只是使用fetch
将文件上传到 http(不是 https)服务器,会遇到TypeError: Network request failed
。
在这里,我使用axios @0.27.2 作为在 Android 手机上运行的客户端成功将文件上传到react-native-file-server作为在另一部 Android 手机上运行的服务器。
客户端需要编辑JAVA和JS代码,服务器不需要编辑JAVA代码。
使用调试版本,必须注释掉此文件 android/app/src/debug/java/com/YOUR_PACKAGE_NAME/ReactNativeFlipper.java 中的第 43 行
38 NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39 NetworkingModule.setCustomClientBuilder(
40 new NetworkingModule.CustomClientBuilder() {
41 @Override
42 public void apply(OkHttpClient.Builder builder) {
43 // builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44 }
45 });
46 client.addPlugin(networkFlipperPlugin);
也许还需要在<application
of android/app/src/main/AndroidManifest.xml
下添加android:usesCleartextTraffic="true"
,在我的测试中,调试和发布版本都不需要。
onFileSelected = async (file) => {
// API ref to the server side BE code `addWebServerFilter("/api/uploadtodir", new WebServerFilter()`
// https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L356
// could not be 'localhost' but IP address
const serverUploadApi = 'http://192.168.1.123:8080/api/uploadtodir';
// the folder on server where file will be uploaded to, could be e.g. '/storage/emulated/0/Download'
const serverFolder = '/storage/emulated/0/FileServerUpload';
const fileToUpload = {
// if want to upload and rename, it can be `name: 'foo.bar'`, but can not be 'foo'
// only if your server upload code support file name without type, on our server
// https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L372
// will cause java.lang.StringIndexOutOfBoundsException in substring()
name: file.name,
// type is necessary in Android, it can be 'image/jpeg' or 'foo/bar', but can not be
// 'foo', 'foo/', '/foo' or undefined, otherwise will cause `[AxiosError: Network Error]`
type: 'a/b',
uri: Platform.OS === 'android' ? file.uri : file.uri.replace('file://', ''),
};
const form = new FormData();
form.append('path', serverFolder);
form.append('uploadfile', fileToUpload);
// ref to the server side FE code `this.axios.post("/api/uploadtodir", parms, config)`
// https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/fileserverwebdoc/src/views/Manage.vue#L411
let res = await axios.post(serverUploadApi, form, {
headers: {
'Content-Type': 'multipart/form-data',
},
onUploadProgress: function (progressEvent) {
console.warn(progressEvent);
},
});
// ref to the server side BE code `return newFixedLengthResponse("Suss");`
// https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L380
if (res.data === 'Suss') {
console.warn('Upload Successful');
} else if (res.data === 'fail') {
console.warn('Upload Failed');
}
};
如果您要连接到 HTTPS 网站,请检查您的模拟器的互联网连接。 (就我而言,我正在使用通过 USB 连接的手机模拟器,并且它的互联网处于离线状态)
为了找到根本问题,我使用XMLHttpRequest
而不是fetch
,并且在发送请求后抛出了一个异常,并带有告诉实际问题HTTP_1_1_REQUIRED
的消息。
显然反应原生(在我的情况下是 v0.59) fetch 只支持 http/1.1 然后我在网络服务器上禁用了 http/2。
如果您的网络服务器是 IIS 看看这个问题的答案
希望这会有所帮助。
React-native Expo 和 Node Express 后端有同样的问题。 问题是关于模拟器本地主机和服务器本地主机之间的冲突。 您的后端服务器可能在 127.0.0.1:8000 上运行,但模拟器无法找到它。
在终端中使用命令“ipconfig”找到您的 IPv4 地址。 例如,它将是 192.138.1.40
之后将其放入您的 fetch ('http://192.138.1.40:8080/')。 同样重要的是 - 使用相同的主机和端口运行您的后端服务器。 以 Node Express 为例:
app.listen(8080, () => console.log("服务器正在运行!"))
android 模拟器的一段时间冷启动工作正常。
只是您在 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);
});
对于 Android 设备,转到您的项目根文件夹并运行以下命令:
adb reverse tcp:[your_own_server_port] tcp:[your_own_server_port]
例如, adb reverse tcp:8088 tcp:8088
这将使您的物理设备(即 Android 手机)监听在您的开发机器(即您的计算机)上运行的 localhost 服务器,地址为http://localhost:[your_own_server_port] 。
之后,您可以在 react-native fetch(
) 调用中直接使用http:localhost:[your_port] /your_api
。
对于 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>
就我而言,Android 模拟器没有连接到 Wi-Fi。
请参阅此处Android Studio - Android Emulator Wifi Connected with No Internet
例:
return fetch('http://<your ip>')
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson)
})
.catch((error) => {
console.error(error);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.