HTTP Fetch fails with "TypeError: Network request failed" => Resolved
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- C++
- Star
- 127k
- Fork
- 25.3k
- Merge trung bình
- 1 ngày 23 giờ
- Pull request đã merge (30 ngày)
- 4
Mô tả
Description
There are 83 issues opened and unanswered about network requests failing with this generic error.
The main causes of the pain are:
- Not getting an answer from the team
- The exception is far too generic and does not suggest the origin of the problem
Problem description
Using fetch to get/post on a HTTPS web server which is using a valid and trusted but not public CA.
- Using Chrome and other apps the requests are always successful and without certificate problems
Sample code in react native:
static async Post(): Promise<string> {
let srv = "my.domain.com";
let port = 5101;
let device = "abcd";
let url = `https://${srv}:${port}/Do/Something?devicename=${device}`;
try {
let response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-type':'application/json'
},
body: JSON.stringify({
key: 'value',
})
});
if(response.status !== 200) throw new Error(`Can't open ${srv} for ${device} with status ${response.status}`);
return response.json();
}
catch(e) {
console.log(e);
throw(e);
}
}
Solution
Due to Android restrictions, a network_security_config configuration must be added to the application. It is an xml file that can be added by following these steps:
- Edit the
android/app/src/main/AndroidManifest.xml - Add the
android:networkSecurityConfig="@xml/network_security_config"to the<application />tag - Create the folder
android/app/src/main/res/xmland inside a file callednetwork_security_config.xml - If you don't want to install the CA in the Android certificates, add the folder
android/app/src/main/res/raw
Variant 1: using the certificates added manually to Android.
In this case the CA must be visible in the User Certificates in the Android Settings. Try using them by opening a website that uses those certificates in Chrome to verify they are valid and correctly installed.
Content of the network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<!-- Localhost config is NEEDED from react-native for the bundling to work -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">127.0.0.1</domain>
<domain includeSubdomains="true">10.0.0.1</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
<domain includeSubdomains="true">my.domain.com</domain>
<trust-anchors>
<certificates src="user"/>
<certificates src="system"/>
</trust-anchors>
</domain-config>
</network-security-config>
The <certificates src="user"/> is the one giving access to the certificates installed manually.
Variant 2: using a certificate bundled with the app
You should export (using ssl) a pem certificate containing just the public key, naming it "ca" (no extension). Copy the certificate in the raw folder
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<!-- Localhost config is NEEDED from react-native for the bundling to work -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">127.0.0.1</domain>
<domain includeSubdomains="true">10.0.0.1</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
<domain includeSubdomains="true">my.domain.com</domain>
<trust-anchors>
<certificates src="@raw/ca"/>
<certificates src="system"/>
</trust-anchors>
</domain-config>
</network-security-config>
Important note (added on June 22, 2022)
The local traffic (with the packager) must be unencrypted. For this reason the <domain-config /> must contain the clearTrafficPermitted=true.
It is also important adding the ip addresses used from react-native when debugging otherwise the application will crash because of the android:networkSecurityConfig="@xml/network_security_config" attribute. If you see the app crashing, take not of the ip used internally from react native and add it/them to this list. For example:
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">127.0.0.1</domain>
<domain includeSubdomains="true">10.0.0.1</domain>
<domain includeSubdomains="true">10.0.1.1</domain>
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
Requested fix: please never throw exceptions with a generic message, they are only a huge pain.
Version
0.67.0
Output of npx react-native info
info Fetching system and libraries information...
System:
OS: Windows 10 10.0.19044
CPU: (8) x64 Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
Memory: 8.20 GB / 31.93 GB
Binaries:
Node: 16.13.0 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
npm: 8.1.3 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK:
API Levels: 19, 23, 25, 26, 27, 28, 29, 30
Build Tools: 19.1.0, 21.1.2, 22.0.1, 23.0.1, 23.0.3, 26.0.2, 27.0.0, 28.0.0, 28.0.3, 29.0.2, 30.0.2
System Images: android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom
Android NDK: 22.1.7171670
Windows SDK:
AllowDevelopmentWithoutDevLicense: Enabled
AllowAllTrustedApps: Enabled
Versions: 10.0.10586.0, 10.0.14393.0, 10.0.15063.0, 10.0.16299.0, 10.0.17134.0, 10.0.17763.0, 10.0.18362.0, 10.0.19041.0
IDEs:
Android Studio: Version 2020.3.0.0 AI-203.7717.56.2031.7935034
Visual Studio: 17.1.32104.313 (Visual Studio Enterprise 2022), 16.11.32002.261 (Visual Studio Enterprise 2019)
Languages:
Java: 1.8.0_302
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: 0.66.4 => 0.66.4
react-native-windows: Not Found
npmGlobalPackages:
react-native: Not Found
Steps to reproduce
Use the above code to make an HTTPS request to a website protected with certificates that are not public.
They will not succeed with a generic exception (as for the issue title)
Repeat the request to a public website and it will succeed.
The issue is the exception being too generic.
Snack, code example, screenshot, or link to a repository
No response
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với các đường dẫn AndroidManifest.xml và network_security_config.xml được mô tả trong issue, sau đó theo dõi cách React Native fetch báo cáo lỗi chứng chỉ trên Android. Hoàn tất có nghĩa là lỗi không còn chỉ xuất hiện dưới dạng lỗi mạng chung chung và hành vi này được bao phủ bởi một test phù hợp của project hoặc một reproduction được dokumentiert.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- android, react-native
- Lĩnh vực
- mobile, networking
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 35/100