Reaktion Native fetch () Netzwerkanforderung fehlgeschlagen

145

Wenn ich ein brandneues Projekt mit react-native init(RN Version 0.29.1) erstelle und einen Abruf in der Rendermethode in die öffentliche Facebook-Demofilm-API einfüge, wird a ausgelöst Network Request Failed. Es gibt einen sehr nutzlosen Stack-Trace und ich kann keine Netzwerkanforderungen in der Chrome-Konsole debuggen. Hier ist der Abruf, den ich sende:

fetch('http://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.movies;
      })
      .catch((error) => {
        console.error(error);
      });
Alek Hurst
quelle
1
Ich bin mir nicht sicher. Ich benutze den iOS-Simulator und dachte, er würde die Internetverbindung meines Computers nutzen
Alek Hurst
Versuchen Sie, den Simulator manuell zu laden und die URL in Safari zu
öffnen
5
http-> https(wenn möglich) wird höchstwahrscheinlich Ihr Problem beheben
Nick Zuber
1
Ich habe die IP 192.168.1.25:3000von verwendet, ifconfigohne meinen Server an diese IP zu bindenrails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio
1
Ja, ich habe alles versucht. Bei mir hat nichts funktioniert
Vigneswaran A

Antworten:

140

Das Problem hierbei ist, dass iOS standardmäßig keine HTTP-Anforderungen zulässt, sondern nur HTTPS. Wenn Sie HTTP-Anforderungen aktivieren möchten, fügen Sie Folgendes hinzu info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Alek Hurst
quelle
2
Diese Antwort hat bei mir funktioniert. Für andere, die neu bei React Native sind, kann diese Datei (info.plist) auch über xcode bearbeitet werden: stackoverflow.com/a/38219454/1299792
Marklar
86
Was ist mit Android? Ich habe das gleiche Problem auch in Android.
Vijay Sharma
16
Genau. Hat jemand die Antwort für Android?
Zach Cook
1
Wenn ich das auf ios / build / info.plist lege und starte: react-native run-ios Das ios / build / info.plist wird überschrieben und meine Änderungen werden beendet. Was soll ich tun?
Jorge Wander Santana Ureña
1
@ JorgeWanderSantanaUreña ändern Sie [Ihr_Projektordnername] / ios / [Ihr_Projektordnername] / In‌ fo.plist
kgosse
58

Es wird nicht empfohlen, alle Domains für http zuzulassen. Machen Sie eine Ausnahme nur für die erforderlichen Domänen.

Quelle: Konfigurieren von Sicherheitsausnahmen für den App-Transport in iOS 9 und OSX 10.11

Fügen Sie der Datei info.plist Ihrer App Folgendes hinzu:

<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>
Lavi Avigdor
quelle
27
Was ist mit Android?
Arisalexis
3
In meiner React Native-App befinden sich anscheinend mehrere info.plist-Dateien in mehreren Verzeichnissen. Irgendeine Idee, welcher Ordner die richtige Datei zum Ändern enthält?
Marklar
2
@ Marklar [Ihr_Projektordnername] / ios / [Ihr_Projektordnername] /Info.plist
Stich
Wenn ich meinen localhost hier verwende: <key> yourserver.com </ key>, wenn ich bereit bin, ihn zu veröffentlichen, muss ich ihn ändern, richtig?
Anayo Oleru
36

Ich habe localhostfür die Adresse verwendet, was offensichtlich falsch war. Nachdem es durch die IP-Adresse des Servers (in dem Netzwerk, in dem sich der Emulator befindet) ersetzt wurde, funktionierte es einwandfrei.

Bearbeiten

In Android Emulator lautet die Adresse des Entwicklungscomputers 10.0.2.2. Mehr Erklärung hier

Für Genymotion lautet die Adresse 10.0.3.2. Mehr Infos hier

Mahmoodvcs
quelle
4
Danke dir. Wahrscheinlich die einzige Antwort, die ich gesehen habe, die für Android funktioniert. Ich habe die IP-Adresse meines Netzwerks verwendet und es funktioniert. zBhttp://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield
1
Vergessen Sie nicht das "http: //" oder es wird nicht funktionieren ... fragte sich, warum es auf Postboten funktionieren würde, aber nicht mit holen
Moucheg
@ Mahmoodvcs Deine Antwort hilft mir sehr, vielen Dank, ich benutze Android Emulator.
Pena Pintada
14

Für uns lag es daran, dass wir eine Datei hochgeladen haben und der RN filePicker nicht den richtigen MIME-Typ angegeben hat. Es gab uns nur "Bild" als Typ. Wir mussten es in 'image / jpg' ändern, damit der Abruf funktioniert.

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })
NickJ
quelle
@JohhanSantana Sie könnten sich wahrscheinlich die Rohbilddaten ansehen und sie von Anfang an abrufen, aber der reaktionsfähige native Picker hat gerade "Bild" für mich zurückgegeben.
NickJ
10

React Native Docs gibt die Antwort darauf.

Apple hat das Laden impliziter Klartext-HTTP-Ressourcen blockiert. Daher müssen wir die folgende Info.plist-Datei (oder eine gleichwertige Datei) unseres Projekts hinzufügen.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

Reagieren Sie auf native Dokumente -> Integration mit vorhandenen Apps -> Testen Sie Ihre Integration -> Ausnahme für App Transport Security hinzufügen

Ozean
quelle
9

Das Problem liegt möglicherweise in der Serverkonfiguration.

Android 7.0 hat einen hier beschriebenen Fehler . Von Vicky Chijwani vorgeschlagene Problemumgehung:

Konfigurieren Sie Ihren Server für die Verwendung der elliptischen Kurve prime256v1. In Nginx 1.10 tun Sie dies beispielsweise, indem Sie ssl_ecdh_curve prime256v1 festlegen.

Dmitry Maksakov
quelle
7

Ich habe das gleiche Problem auf Android, aber ich habe es geschafft, eine Lösung dafür zu finden. Android blockiert den Klartextverkehr (Nicht-https-Anfragen) seit API Level 28 standardmäßig. React-native fügt der Debug-Version ( android/app/src/debug/res/xml/react_native_config.xml) jedoch eine Netzwerksicherheitskonfiguration hinzu, die einige Domänen (localhost und die Host-IPs für AVD / Genymotion) definiert, die im Entwicklungsmodus ohne SSL verwendet werden können. Sie können dort Ihre Domain hinzufügen, um http-Anfragen zuzulassen.

<?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>
Johannes Spohr
quelle
Dies funktionierte für mich mit reagieren native 0,59 und Ziel SDK 28 :)
Sameera Madushan
7

Ich habe das gleiche Problem auf Android 9 aufgrund des "http" und des Problems, das durch einfaches Hinzufügen von android behoben wurde: usingCleartextTraffic = "true" in 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>

kautikmistry
quelle
2
Danke, das hat auch bei mir funktioniert. Es passiert, weil Android HTTP auf API 28 standardmäßig nicht mehr unterstützt.
Gui Herzog
5

Ich bin auf dasselbe Problem im Android Emulator gestoßen, bei dem ich versucht habe, auf eine externe HTTPS-URL mit einem gültigen Zertifikat zuzugreifen. Das Abrufen dieser URL in React-Native ist jedoch fehlgeschlagen

'fetch error:', { [TypeError: Network request failed]
sourceURL: 'http://10.0.2.2:8081/index.delta?platform=android&dev=true&minify=false' }

1) Um den genauen Fehler in den Protokollen herauszufinden, habe ich zuerst 'JS remote debuggen' mit Cmd + M in der App aktiviert

2) Der gemeldete Fehler war

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

3) Ich habe das gültige Zertifikat der URL mit dieser Methode hinzugefügt -> SCHRITT 2

http://lpains.net/articles/2018/install-root-ca-in-android/

Dieses Zertifikat wird der Registerkarte Benutzer hinzugefügt.

4) Fügen Sie das android:networkSecurityConfigAttributattribut zu AndroidManifest.xml hinzu

Fügen Sie eine Netzwerksicherheitskonfigurationsdatei hinzu 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>

Dies sollte funktionieren und Ihnen eine erwartete Antwort geben.

Henryoats
quelle
Ich musste nur Schritt 4 machen, um zu arbeiten. Vielen Dank!
Bruno Serrano
4

Ich hatte dieses Problem für Android-

URL- localhost / authToken.json - hat nicht funktioniert :(

URL- 10.106.105.103/authToken.json - hat nicht funktioniert :(

URL- http://10.106.105.103/authToken.json - funktioniert :): D.

Hinweis: Verwenden Sie diese Option ifconfigunter Linux oder ipconfigWindows, um die IpAddress des Computers zu finden

Varun Kumar
quelle
4

Für Android-Nutzer:

  1. Ersetzen Sie localhosts durch eine Lan-IP-Adresse, da localhost beim Ausführen des Projekts auf einem Android-Gerät auf das Android-Gerät anstatt auf Ihren Computer zeigt. Beispiel: Wechseln http://localostzuhttp://192.168.1.123

  2. Wenn Ihre Anforderungs-URL HTTPS lautet und sich Ihr Android-Gerät unter einem Proxy befindet, nehmen Sie an, dass Sie eine vom Benutzer hinzugefügte Zertifizierungsstelle (wie die Zertifizierungsstelle der Burp Suite oder die Zertifizierungsstelle von Charles) auf Ihrem Android-Gerät installiert haben. Stellen Sie sicher, dass Ihre Android-Version unter Nougat (7.0) liegt , da : Änderungen an vertrauenswürdigen Zertifizierungsstellen in Android Nougat

    Vom Benutzer hinzugefügte Zertifizierungsstellen Der
    Schutz aller Anwendungsdaten ist ein Hauptziel der Sandbox für Android-Anwendungen. Android Nougat ändert die Interaktion von Anwendungen mit von Benutzern und Administratoren bereitgestellten Zertifizierungsstellen. Standardmäßig werden Apps, die auf API-Ebene 24 abzielen, solche Zertifizierungsstellen standardmäßig nicht berücksichtigen, es sei denn, die App entscheidet sich ausdrücklich dafür. Diese Standardeinstellung für die Sicherheit reduziert die Angriffsfläche von Anwendungen und fördert den konsistenten Umgang mit netzwerk- und dateibasierten Anwendungsdaten.

Fangxing
quelle
3

Für Android haben Sie möglicherweise die Berechtigung in AndroidManifest.xml nicht hinzugefügt. Sie müssen die folgende Berechtigung hinzufügen.

<uses-permission android:name="android.permission.INTERNET" /> 
Shashwat
quelle
Gibt es eine andere Problemumgehung, obwohl ich diesen Fehler erhalte?
masud_moni
@masud_moni finden Sie einen Weg, um das Problem zu beheben?
Ich habe
@RafaelRotiroti Ja, ich habe dieses Problem gelöst, aber obwohl es eine Weile her ist, ist es schwer zu merken, wenn Sie die Erlaubnis verwendet haben und immer noch Probleme haben, teilen Sie uns bitte Details mit. Ich werde mein Bestes geben, um zu helfen, und Sie werden auch andere haben, die sich darum kümmern
masud_moni
@masud_moni danke, ich habe dieses Problem mit der IP behoben, die nach dem Befehl ifconfig angegeben wurde. AVD erstellt ein virtuelles Gerät und verwendet daher dieselbe Theorie wie virtuelle Maschinen, die in 127.0.0.1 auf meinem Gerät nicht gehostet werden. Also benutze ich 192.168.xx IP und alles funktioniert auch gut
Rafael Rotiroti
2

Ich habe ein ähnliches Problem. In meinem Fall funktionierten Anfragen an localhost und hörten plötzlich auf. Es stellte sich heraus, dass das Problem darin bestand, dass ich mein WLAN auf meinem Android-Handy ausschaltete.

Ивайло Янков
quelle
2

Dies funktionierte für mich, Android verwendet eine spezielle Art von IP-Adresse 10.0.2.2 dann Portnummer

import { Platform } from 'react-native';

export const baseUrl = Platform.OS === 'android' ?
    'http://10.0.2.2:3000/'
: 
'http://localhost:3000/';
Cho Cho
quelle
1

Wenn Sie Docker für die REST-API verwenden, bestand ein funktionierender Fall für mich darin, den Hostnamen: http://demo.test/apidurch die IP-Adresse des Computers zu ersetzen : http://x.x.x.x/api. Sie können die IP-Adresse ermitteln, indem Sie überprüfen, welche IPv4-Datei in Ihrem drahtlosen Netzwerk vorhanden ist. Sie sollten auch das WLAN vom Telefon aus haben.

Craciun Ciprian
quelle
1

Sie sollten den Fehlerfall in .then für die Abruf-API behandeln.

Beispielsweise:

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;
});
user3374790
quelle
0
  1. In android:usesCleartextTraffic="true"Zeile in AndroidManifest.xml.

  2. Löschen Sie alle Debug-Ordner aus Ihrem Android-Ordner.

devkrkanhaiya
quelle
-1

Nur Sie haben Änderungen in 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);
     });
Lavaraju
quelle
-1

Wechseln Sie für Android-Geräte zu Ihrem Projektstammordner und führen Sie den folgenden Befehl aus:

adb reverse tcp:[your_own_server_port] tcp:[your_own_server_port]

z.B, adb reverse tcp:8088 tcp:8088

Dadurch hört Ihr physisches Gerät (dh das Android-Telefon) den auf Ihrem Entwicklungscomputer (dh Ihrem Computer) laufenden localhost-Server unter der Adresse http: // localhost: [your_own_server_port] ab .

Danach können Sie direkt http:localhost:[your_port] /your_apiin Ihrem reaktionsnativen fetch(Aufruf verwenden.

Preetam Keshari Nahak
quelle
-1

Fügen Sie für Android android: networkSecurityConfig = "@ xml / network_security_config" zum Anwendungstag in AndroidManifest.xml hinzu:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ... >
        <application android:networkSecurityConfig="@xml/network_security_config"
                        ... >
            ...
        </application>
    </manifest>

Inhalt der Datei 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>
xyz
quelle
Könnten Sie bitte näher darauf eingehen und Einzelheiten erläutern? Ich bin nur neugierig, wie es funktioniert?
Ganeshdeshmukh
Habe den Kommentar geändert, hoffe das wird helfen
xyz
-5

Beispiel:

return fetch('http://<your ip>')
  .then((response) => response.json())
  .then((responseJson) => {
    console.log(responseJson)
  })
  .catch((error) => {
    console.error(error);
  });
Akhila Antony
quelle