Repository: react-native
Issue: HTTP Fetch fails with "TypeError: Network request failed" => Resolved
Labels: 🌐Networking,Needs: Triage :mag:

### Description

There are 83 issues opened and unanswered about network requests failing with this generic error.
The main causes of the pain are:
1. Not getting an answer from the team
2. 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:
1. Edit the `android/app/src/main/AndroidManifest.xml`
2. Add the `android:networkSecurityConfig="@xml/network_security_config"` to the `<application />` tag
3. Create the folder `android/app/src/main/res/xml` and inside a file called `network_security_config.xml`
4. 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_