React Native fetch () Richiesta di rete non riuscita


146

Quando creo un nuovo progetto utilizzando react-native init(versione RN 0.29.1) e inserisco un metodo di rendering nell'API del film demo pubblico di Facebook, viene generato un Network Request Failed. C'è una traccia dello stack molto inutile e non riesco a eseguire il debug delle richieste di rete nella console Chrome. Ecco il recupero che sto inviando:

fetch('http://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.movies;
      })
      .catch((error) => {
        console.error(error);
      });

1
Non ne sono sicuro. Sto usando il simulatore iOS e ho pensato che usasse la connessione Internet del mio computer
Alek Hurst, il

Prova a caricare manualmente il simulatore e ad aprire l'URL in Safari
FuzzyTree,

5
http-> https(se possibile) molto probabilmente risolverà il tuo problema
Nick Zuber,

1
Stavo usando l'ip 192.168.1.25:3000da ifconfigsenza legarsi mio server a quella iprails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio

1
Sì, ho provato di tutto. Niente ha funzionato per me
Vigneswaran A

Risposte:


140

Il problema qui è che iOS non consente le richieste HTTP per impostazione predefinita, solo HTTPS. Se vuoi abilitare le richieste HTTP aggiungi questo al tuo info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

2
Questa risposta ha funzionato per me. Per altri nuovi a React Native, questo file (info.plist) può anche essere modificato tramite xcode: stackoverflow.com/a/38219454/1299792
Marklar

86
che dire di android? Sto affrontando lo stesso problema anche in Android.
Vijay Sharma,

16
Esattamente. Qualcuno ha la risposta per Android?
Zach Cook,

1
quando lo inserisco su ios / build / info.plist ed eseguo: reag-native run-ios Il file ios / build / info.plist viene sovrascritto ed esco dalle modifiche Cosa devo fare?
Jorge Wander Santana Ureña,

1
@ JorgeWanderSantanaUreña modifica [nome_progetto_del_programma] / ios / [nome_folder_progetto] / In‌ fo.plist
kgosse

58

Non è consigliato consentire tutti i domini per http. Fai un'eccezione solo per i domini necessari.

Fonte: configurazione delle eccezioni di sicurezza del trasporto app in iOS 9 e OSX 10.11

Aggiungi quanto segue al file info.plist della tua app:

<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>

27
che dire di android?
arisalexis,

3
Sembra che ci siano più file info.plist in più directory nella mia app React Native. Qualche idea su quale cartella contenga il file corretto da modificare?
Marklar,

2
@Marklar [your_project_folder_name] / ios / [your_project_folder_name] /Info.plist
Stich

se uso il mio localhost qui: <key> yourserver.com </key>, quando sono pronto per la pubblicazione, dovrò cambiarlo, giusto?
Anayo Oleru

36

Stavo usando localhostl'indirizzo, che ovviamente era sbagliato. Dopo averlo sostituito con l'indirizzo IP del server (nella rete dell'emulatore), ha funzionato perfettamente.

modificare

In Android Emulator, l'indirizzo della macchina di sviluppo è 10.0.2.2. Altre spiegazioni qui

Per Genymotion, l'indirizzo è 10.0.3.2. Maggiori informazioni qui


4
Grazie. Probabilmente l'unica risposta che ho visto che funziona per Android. Ho usato l'indirizzo IP delle mie reti e funziona. ad es.http://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield,

1
Non dimenticare "http: //" altrimenti non funzionerà ... mi chiedevo perché avrebbe funzionato con il postino ma non con il recupero
Moucheg

@Mahmoodvcs La tua risposta mi aiuta molto, grazie mille, sto usando l'emulatore Android.
Pena Pintada,

14

Per noi è stato perché stavamo caricando un file e il file RN filePicker non ha fornito il tipo MIME corretto. Ci ha appena dato "immagine" come tipo. Abbiamo dovuto cambiarlo in 'image / jpg' per far funzionare il recupero.

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })

@JohhanSantana Probabilmente potresti guardare i dati delle immagini grezze e ottenerli dall'inizio, ma il selettore nativo reattivo è appena tornato 'immagine' per me.
NickJ,

10

React Native Docs dà la risposta per questo.

Apple ha bloccato il caricamento implicito di risorse HTTP in chiaro. Quindi dobbiamo aggiungere il seguente file Info.plist (o equivalente) del nostro progetto.

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

Reagisci documenti nativi -> Integrazione con app esistenti -> Verifica la tua integrazione -> Aggiungi eccezione di sicurezza trasporto app


9

Il problema potrebbe essere nella configurazione del server.

Android 7.0 ha un bug descritto qui . Soluzione proposta da Vicky Chijwani:

Configurare il server per utilizzare la curva ellittica prime256v1. Ad esempio, in Nginx 1.10 lo fai impostando ssl_ecdh_curve prime256v1;


7

Ho avuto lo stesso problema su Android ma sono riuscito a trovare una soluzione per questo. Android sta bloccando il traffico in chiaro (richieste non https) dal livello API 28 per impostazione predefinita. Reattivo nativo aggiunge tuttavia una configurazione di sicurezza della rete alla versione di debug ( android/app/src/debug/res/xml/react_native_config.xml) che definisce alcuni domini (localhost e IP host per AVD / Genymotion), che possono essere utilizzati senza SSL in modalità dev. Puoi aggiungere il tuo dominio lì per consentire le richieste 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>

Questo ha funzionato per me con reagire nativo 0,59 e target sdk 28 :)
sameera madushan

7

Ho avuto lo stesso problema su Android 9 a causa di "http" e il problema è stato risolto semplicemente aggiungendo android: useCleartextTraffic = "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>


2
Grazie, ha funzionato anche per me. Succede perché Android non supporta più HTTP per impostazione predefinita su API 28.
Gui Herzog

5

Mi sono imbattuto nello stesso problema su Android Emulator, dove ho provato ad accedere a un URL HTTPS esterno con un certificato valido. Ma recuperare quell'URL in React-native non è riuscito

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

1) Per scoprire l'esatto errore nei log, ho prima abilitato 'Debug JS Remotoy' usando Cmd + M sull'app

2) L'errore segnalato era

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

3) Ho aggiunto il certificato valido dell'URL usando questo metodo -> PASSAGGIO 2

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

Questo certificato viene aggiunto alla scheda Utente.

4) Aggiungi l'attributo android:networkSecurityConfigdell'attributo ad AndroidManifest.xml

Aggiungi un file di configurazione della sicurezza di rete 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>

Questo dovrebbe funzionare e darti una risposta prevista.


Avevo solo bisogno di fare il passo 4 per funzionare. Grazie!
Bruno Serrano,

4

Stavo avendo questo problema per Android-

URL- localhost / authToken.json - non ha funzionato :(

URL- 10.106.105.103/authToken.json - non ha funzionato :(

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

Nota: utilizzare ifconfigsu Linux o ipconfigsu Windows per trovare l'indirizzo IP della macchina


4

Per utenti Android:

  1. Sostituisci localhosts con indirizzi IP Lan perché quando esegui il progetto su un dispositivo Android, localhost punta al dispositivo Android, anziché al tuo computer, ad esempio: cambia http://localostinhttp://192.168.1.123

  2. Se l'URL della tua richiesta è HTTPS e il tuo dispositivo Android è sotto un proxy, supponi di aver installato la CA aggiunta dall'utente (come la CA di burp suite o la CA di Charles) nel tuo dispositivo Android, assicurati che la tua versione di Android sia inferiore a Nougat (7.0) , perché : Modifiche alle autorità di certificazione attendibili in Android Nougat

    CA aggiunte dall'utente La
    protezione di tutti i dati dell'applicazione è un obiettivo chiave della sandbox dell'applicazione Android. Android Nougat modifica il modo in cui le applicazioni interagiscono con le CA fornite dall'utente e dall'amministratore. Per impostazione predefinita, le app che hanno come target il livello API 24, per impostazione predefinita, non onoreranno tali CA a meno che l'app non accetti esplicitamente. Questa impostazione sicura per impostazione predefinita riduce la superficie di attacco delle applicazioni e incoraggia la gestione coerente della rete e dei dati delle applicazioni basate su file.


3

Per Android, potresti non aver aggiunto l'autorizzazione in AndroidManifest.xml È necessario aggiungere l'autorizzazione seguente.

<uses-permission android:name="android.permission.INTERNET" /> 

L'ho già fatto anche se sto riscontrando quell'errore, c'è qualche altra soluzione?
masud_moni,

@masud_moni trovi il modo di risolvere il problema? sto ancora avendo lo stesso problema
Rafael Rotiroti,

@RafaelRotiroti sì, ho risolto il problema, ma anche se è passato un po 'di tempo, è difficile ricordare, se hai utilizzato l'autorizzazione e stai ancora affrontando i problemi, ti preghiamo di condividere i dettagli. Farò del mio meglio per aiutare, e ne avrai anche altri che lo esamineranno
masud_moni,

@masud_moni grazie, ho risolto quel problema usando l'ip dato dopo aver eseguito il comando ifconfig. AVD crea un dispositivo virtuale, quindi utilizzando la stessa teoria delle macchine virtuali che non è ospitato in 127.0.0.1 nel mio dispositivo. Quindi uso 192.168.xx IP e tutto funziona bene
Rafael Rotiroti,

2

Ho un problema simile Nel mio caso le richieste a localhost funzionavano e improvvisamente si fermarono. Si è scoperto che il problema era che stavo disattivando il mio wifi sul mio telefono Android.


2

Questo ha funzionato per me, Android utilizza un tipo speciale di indirizzo IP 10.0.2.2 quindi il numero di porta

import { Platform } from 'react-native';

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

1

se si utilizza finestra mobile per l'API REST, un caso che lavora per me era quello di sostituire hostname: http://demo.test/apicon l'indirizzo IP della macchina: http://x.x.x.x/api. Puoi ottenere l'IP controllando quale ipv4 hai sulla tua rete wireless. Dovresti anche avere il wifi dal telefono acceso.


1

Dovresti gestire il caso di errore in .then per l'API di recupero.

Per esempio:

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
  1. Aggiungi android:usesCleartextTraffic="true"riga in AndroidManifest.xml.

  2. Elimina tutta la cartella di debug dalla tua cartella Android.


0

Puoi gestirlo usando questo:

catch((error) => {
      this.setState({
        typing_animation_button: false,
      });
      console.log(error);
      if ('Timeout' || 'Network request failed') {
        toast_show = true;
        toast_type = 'error';
        toast_text = 'Network failure';
      }
      this.setState({
        disable_button: false,
      });
    });

-1

Solo tu hai modifiche 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);
     });

-1

Per i dispositivi Android, vai alla cartella principale del progetto ed esegui il comando:

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

per esempio, adb reverse tcp:8088 tcp:8088

Questo farà sì che il tuo dispositivo fisico (ad es. Un telefono Android) ascolti il ​​server localhost in esecuzione sul tuo computer di sviluppo (ad es. Il tuo computer) all'indirizzo http: // localhost: [your_own_server_port] .

Dopodiché, puoi usare direttamente la http:localhost:[your_port] /your_apitua fetch(chiamata di reazione nativa .


-1

Per Android, aggiungi Android: networkSecurityConfig = "@ xml / network_security_config" al tag dell'applicazione in AndroidManifest.xml, in questo modo:

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

contenuto del file 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>

potresti per favore elaborare e spiegare in dettaglio? Sono solo curioso di sapere come funziona?
Ganeshdeshmukh,

Ho modificato il commento, spero che possa essere d'aiuto
xyz

-5

Esempio:

return fetch('http://<your ip>')
  .then((response) => response.json())
  .then((responseJson) => {
    console.log(responseJson)
  })
  .catch((error) => {
    console.error(error);
  });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.