La solicitud de red React fetch () falló

146

Cuando creo un nuevo proyecto usando react-native init(RN versión 0.29.1) y pongo una búsqueda en el método de renderizado en la API pública de la película de demostración de Facebook, arroja un Network Request Failed. Hay un seguimiento de pila muy inútil y no puedo depurar solicitudes de red en la consola de Chrome. Aquí está la búsqueda que estoy enviando:

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
fuente
1
No estoy seguro. Estoy usando el simulador de iOS y pensé que usaba la conexión a Internet de mi computadora
Alek Hurst
Intente cargar el simulador manualmente y abrir la url en safari
FuzzyTree
55
http-> https(si es posible) probablemente solucionará tu problema
Nick Zuber
1
Estaba usando la ip 192.168.1.25:3000desde ifconfigsin vincular mi servidor a esa iprails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio
1
Sí, lo intenté todo. Nada funcionó para mí
Vigneswaran A

Respuestas:

140

El problema aquí es que iOS no permite solicitudes HTTP por defecto, solo HTTPS. Si desea habilitar las solicitudes HTTP, agregue esto a su info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Alek Hurst
fuente
2
Esta respuesta funcionó para mí. Para otros nuevos en React Native, este archivo (info.plist) también se puede editar a través de xcode: stackoverflow.com/a/38219454/1299792
Marklar
86
¿Qué hay de Android? Estoy enfrentando el mismo problema en Android también.
Vijay Sharma
16
Exactamente. Alguien tiene la respuesta para Android?
Zach Cook
1
cuando pongo eso en ios / build / info.plist y ejecuto: react-native run-ios El ios / build / info.plist se sobrescribe y sale de mis cambios ¿Qué debo hacer?
Jorge Wander Santana Ureña
1
@ JorgeWanderSantanaUreña modificar [your_project_folder_name] / ios / [your_project_folder_name] / In‌ fo.plist
kgosse
58

No se recomienda permitir todos los dominios para http. Haga una excepción solo para los dominios necesarios.

Fuente: Configuración de excepciones de seguridad de transporte de aplicaciones en iOS 9 y OSX 10.11

Agregue lo siguiente al archivo info.plist de su aplicación:

<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
fuente
27
¿Qué hay de Android?
arisalexis
3
Parece que hay múltiples archivos info.plist en múltiples directorios en mi aplicación React Native. ¿Alguna idea de qué carpeta contiene el archivo correcto para cambiar?
Marklar
2
@Marklar [your_project_folder_name] / ios / [your_project_folder_name] /Info.plist
Stich
si uso mi localhost aquí: <key> yourserver.com </key>, cuando esté listo para publicar, tendré que cambiarlo, ¿correcto?
Anayo Oleru
36

Estaba usando localhostla dirección, que obviamente estaba mal. Después de reemplazarlo con la dirección IP del servidor (en la red que es el emulador), funcionó perfectamente.

Editar

En Android Emulator, la dirección de la máquina de desarrollo es 10.0.2.2. Más explicaciones aquí

Para Genymotion, la dirección es 10.0.3.2. Más información aquí.

Mahmoodvcs
fuente
44
Gracias. Probablemente la única respuesta que he visto que funciona para Android. Usé la dirección IP de mi red y funciona. por ejemplohttp://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield
1
No olvides el "http: //" o de lo contrario no funcionará ... me preguntaba por qué funcionaría en cartero pero no con búsqueda
Moucheg
@Mahmoodvcs Tu respuesta me ayudó mucho, muchas gracias, estoy usando el emulador de Android.
Pena Pintada
14

Para nosotros fue porque estábamos cargando un archivo y el RN filePicker no proporcionó el tipo mime adecuado. Simplemente nos dio 'imagen' como tipo. Necesitábamos cambiarlo a 'image / jpg' para que la búsqueda funcionara.

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })
NickJ
fuente
@JohhanSantana Probablemente podría mirar los datos de la imagen sin procesar y obtenerlos desde el principio, pero el selector nativo de reacción acaba de regresar 'imagen' para mí.
NickJ
10

React Native Docs da la respuesta para esto.

Apple ha bloqueado la carga implícita de recursos HTTP de texto en claro. Por lo tanto, debemos agregar el siguiente archivo Info.plist (o equivalente) de nuestro proyecto.

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

Reaccionar documentos nativos -> Integración con aplicaciones existentes -> Probar su integración -> Agregar excepción de seguridad de transporte de aplicaciones

Oceano
fuente
9

El problema puede estar en la configuración del servidor.

Android 7.0 tiene un error descrito aquí . Solución propuesta por Vicky Chijwani:

Configure su servidor para usar la curva elíptica prime256v1. Por ejemplo, en Nginx 1.10, hace esto configurando ssl_ecdh_curve prime256v1;

Dmitry Maksakov
fuente
7

Tuve el mismo problema en Android, pero logré encontrar una solución. Android está bloqueando el tráfico de texto sin formato (solicitudes que no son https) desde el nivel 28 de API de forma predeterminada. Sin embargo, react-native agrega una configuración de seguridad de red a la versión de depuración ( android/app/src/debug/res/xml/react_native_config.xml) que define algunos dominios (localhost y las IP de host para AVD / Genymotion), que se pueden usar sin SSL en modo dev. Puede agregar su dominio allí para permitir solicitudes 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>
Johannes Spohr
fuente
Esto funcionó para mí con reaccionar nativo 0.59 y objetivo sdk 28 :)
sameera madushan
7

Tengo el mismo problema en Android 9 debido a "http" y el problema se resolvió simplemente agregando android: usesCleartextTraffic = "true" en 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
fuente
2
Gracias, esto también funcionó para mí. Ocurre porque Android ya no es compatible con HTTP por defecto en API 28.
Gui Herzog
5

Me encontré con el mismo problema en el emulador de Android, donde intenté acceder a una URL HTTPS externa con un certificado válido. Pero no se pudo recuperar esa URL en react-native

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

1) Para descubrir el error exacto en los registros, primero habilité 'Debug JS Remotely' usando Cmd + M en la aplicación

2) El error reportado fue

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

3) Agregué el certificado válido de la URL usando este método -> PASO 2

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

Este certificado se agrega a la pestaña Usuario.

4) Agregue el atributo de android:networkSecurityConfigatributo a AndroidManifest.xml

Agregar un archivo de configuración de seguridad de red 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>

Esto debería funcionar y darle una respuesta esperada.

henryoats
fuente
Solo necesitaba hacer el paso 4 para trabajar. ¡Gracias!
Bruno Serrano
4

Estaba teniendo este problema para Android

URL- localhost / authToken.json - no funcionó :(

URL- 10.106.105.103/authToken.json - no funcionó :(

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

Nota: use ifconfigen Linux o ipconfigen Windows para encontrar la máquina IpAddress

Varun Kumar
fuente
4

Para usuarios de Android:

  1. Reemplace localhosts por una dirección IP de Lan porque cuando ejecuta el proyecto en un dispositivo Android, localhost apunta al dispositivo Android, en lugar de a su computadora, por ejemplo: cambie http://localostahttp://192.168.1.123

  2. Si su URL de solicitud es HTTPS y su dispositivo Android está bajo un proxy, suponga que ha instalado una CA agregada por el usuario (como la CA de burp suite o la CA de Charles) en su dispositivo Android, asegúrese de que su versión de Android esté por debajo de Nougat (7.0) , porque : Cambios en las autoridades de certificación de confianza en Android Nougat

    CA agregadas por el usuario La
    protección de todos los datos de la aplicación es un objetivo clave del entorno limitado de aplicaciones de Android. Android Nougat cambia la forma en que las aplicaciones interactúan con las CA proporcionadas por el usuario y el administrador. De manera predeterminada, las aplicaciones que se dirigen al nivel 24 de API, por diseño, no honrarán tales CA a menos que la aplicación explícitamente opte por esta opción.

fangxing
fuente
3

Para Android, es posible que no haya agregado el permiso en AndroidManifest.xml. Necesita agregar el siguiente permiso.

<uses-permission android:name="android.permission.INTERNET" /> 
Shashwat
fuente
Ya tengo eso a pesar de que recibo ese error, ¿hay alguna otra solución?
masud_moni
@masud_moni, ¿encuentra la manera de solucionar el problema? sigo teniendo el mismo problema
Rafael Rotiroti
@RafaelRotiroti sí, resolví ese problema, pero aunque ha pasado un tiempo, es difícil de recordar, si ha utilizado el permiso y aún enfrenta problemas, comparta detalles. Yo haré todo lo posible para ayudar, y que tendrá también a otros a mirar en él
masud_moni
@masud_moni gracias, he solucionado ese problema usando la ip dada después de ejecutar el comando ifconfig. AVD crea un dispositivo virtual, por lo que utiliza la misma teoría que las máquinas virtuales que no tiene nada alojado en 127.0.0.1 en mi dispositivo. Entonces uso 192.168.xx IP y todo funciona bien también
Rafael Rotiroti
2

Tengo un problema similar En mi caso, las solicitudes a localhost funcionaban y de repente se detuvieron. Resultó que el problema era que estaba apagando mi wifi en mi teléfono Android.

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

Esto funcionó para mí, Android usa un tipo especial de dirección IP 10.0.2.2 y luego número de puerto

import { Platform } from 'react-native';

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

si utiliza cargador de muelle para la API REST, un caso de trabajo para mí fue la de sustituir el nombre de host: http://demo.test/apila dirección IP de la máquina: http://x.x.x.x/api. Puede obtener la IP comprobando qué ipv4 tiene en su red inalámbrica. También debe tener el wifi del teléfono encendido.

Craciun Ciprian
fuente
1

Debe manejar el caso de error en .then para buscar API.

Por ejemplo:

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;
});
usuario3374790
fuente
0
  1. Agregar android:usesCleartextTraffic="true"línea en AndroidManifest.xml.

  2. Elimine toda la carpeta de depuración de su carpeta de Android.

devkrkanhaiya
fuente
0

Puedes manejarlo usando esto:

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,
      });
    });
Talha Fiaz
fuente
-1

Solo tienes cambios en 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
fuente
-1

Para dispositivos Android, vaya a la carpeta raíz del proyecto y ejecute el comando:

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

p.ej, adb reverse tcp:8088 tcp:8088

Esto hará que su dispositivo físico (es decir, un teléfono Android) escuche el servidor localhost que se ejecuta en su máquina de desarrollo (es decir, su computadora) en la dirección http: // localhost: [your_own_server_port] .

Después de eso, puede usar directamente http:localhost:[your_port] /your_apien su fetch(llamada react-native ).

Preetam Keshari Nahak
fuente
-1

Para Android, agregue android: networkSecurityConfig = "@ xml / network_security_config" a la etiqueta de la aplicación en AndroidManifest.xml, de esta manera:

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

contenido del archivo 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
fuente
¿podría por favor elaborar y explicar en detalle? Tengo curiosidad por cómo funciona?
ganeshdeshmukh
Han modificado el comentario, la esperanza de que le ayudará
xyz
-5

Ejemplo:

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