Skip to content

HTTP Fetch fails with "TypeError: Network request failed" => Resolved #32931

Description

@raffaeler

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions