Falha na solicitação de rede de busca nativa ()

146

Quando crio um projeto react-native inittotalmente novo usando (RN versão 0.29.1) e coloco uma busca no método de renderização na API pública de filme de demonstração do facebook, ele lança a Network Request Failed. Há um rastreamento de pilha muito inútil e não consigo depurar solicitações de rede no console do chrome. Aqui está a busca que estou 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
fonte
1
Não tenho certeza. Estou usando o simulador do iOS e achei que ele usava a conexão de internet do meu computador
Alek Hurst
Tente carregar o simulador manualmente e abrir o URL no safari
FuzzyTree 17/07/16
5
http-> https(se possível) provavelmente irá corrigir o problema
Nick Zuber
1
Eu estava usando o ip 192.168.1.25:3000de ifconfigsem vincular meu servidor a esse iprails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio
1
Sim, eu tentei tudo. Nada funcionou para mim
Vigneswaran A

Respostas:

140

O problema aqui é que o iOS não permite solicitações HTTP por padrão, apenas HTTPS. Se você deseja ativar solicitações HTTP, adicione isso ao seu info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Alek Hurst
fonte
2
Essa resposta funcionou para mim. Para outros novos para reagir Native, este arquivo (info.plist) também podem ser editados através Xcode: stackoverflow.com/a/38219454/1299792
Marklar
86
e o android? Estou enfrentando o mesmo problema no android também.
Vijay Sharma
16
Exatamente. Alguém tem a resposta para o android?
Zach Cook
1
quando coloco isso no ios / build / info.plist e execute: react-native run-ios O ios / build / info.plist é substituído e sai das minhas alterações O que devo fazer?
Jorge Wander Santana Ureña
1
@ JorgeWanderSantanaUreña modifique [your_project_folder_name] / ios / [your_project_folder_name] / In‌ fo.plist
kgosse
58

Não recomendado para permitir todos os domínios para http. Faça uma exceção apenas para os domínios necessários.

Fonte: Configurando exceções de segurança do App Transport no iOS 9 e OSX 10.11

Adicione o seguinte ao arquivo info.plist do seu aplicativo:

<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
fonte
27
e o android?
Arisalexis
3
Parece haver vários arquivos info.plist em vários diretórios no meu aplicativo React Native. Alguma idéia de qual pasta contém o arquivo correto a ser alterado?
Marklar 28/02
2
@Marklar [your_project_folder_name] / ios / [your_project_folder_name] /Info.plist
Stich
se eu usar meu host local aqui: <key> YOURServer.com </key>, quando estiver pronto, estou pronto para publicar, precisarei alterá-lo, correto?
Anayo Oleru
36

Eu estava usando localhosto endereço, o que obviamente estava errado. Depois de substituí-lo pelo endereço IP do servidor (na rede em que está o emulador), funcionou perfeitamente.

Editar

No Android Emulator, o endereço da máquina de desenvolvimento é 10.0.2.2. Mais explicações aqui

Para Genymotion, o endereço é 10.0.3.2. Mais informações aqui

Mahmoodvcs
fonte
4
Obrigado. Provavelmente a única resposta que vi que funciona para o Android. Utilizei o endereço IP da minha rede e funciona. por exemplohttp://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield
1
Não se esqueça do "http: //" ou então não vai funcionar ... queria saber por que ele iria trabalhar em carteiro, mas não com fetch
Moucheg
@Mahmoodvcs Sua resposta me ajuda muito, muito obrigado, estou usando o emulador Android.
Pena Pintada
14

Para nós, foi porque estávamos carregando um arquivo e o RN filePicker não forneceu o tipo mime adequado. Apenas nos deu 'imagem' como o tipo. Precisávamos alterá-lo para 'image / jpg' para que a busca funcionasse.

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })
NickJ
fonte
@JohhanSantana Você provavelmente poderia olhar para os dados brutos da imagem e obtê-los desde o início, mas o seletor nativo de reação acabou de retornar 'imagem' para mim.
NickJ
10

O React Native Docs fornece a resposta para isso.

A Apple bloqueou o carregamento implícito de recursos de texto não criptografado. Portanto, precisamos adicionar o seguinte arquivo Info.plist (ou equivalente) do nosso projeto.

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

Reagir documentos nativos -> integração com aplicativos existentes -> testar sua integração -> exceção Adicionar segurança de transporte de aplicativos

oceano
fonte
9

O problema pode estar na configuração do servidor.

O Android 7.0 tem um bug descrito aqui . Solução proposta por Vicky Chijwani:

Configure seu servidor para usar a curva elíptica prime256v1. Por exemplo, no Nginx 1.10, você faz isso definindo ssl_ecdh_curve prime256v1;

Dmitry Maksakov
fonte
7

Eu tive o mesmo problema no Android, mas consegui encontrar uma solução para ele. O Android está bloqueando o tráfego de texto não criptografado (sem solicitações https) desde o nível 28 da API, por padrão. No entanto, o react-native adiciona uma configuração de segurança de rede à versão de depuração ( android/app/src/debug/res/xml/react_native_config.xml) que define alguns domínios (host local e os IPs do host para AVD / Genymotion), que podem ser usados ​​sem SSL no modo dev. Você pode adicionar seu domínio lá para permitir solicitações 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
fonte
Isso funcionou para mim com reagir nativo 0,59 e alvo sdk 28 :) #
sameera madushan
7

Eu tive o mesmo problema no Android 9 por causa do "http" e o problema foi resolvido com a adição do android: usesCleartextTraffic = "true" no 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
fonte
2
Obrigado, isso funcionou para mim também. Isso acontece porque o Android não está suportando HTTP mais por padrão na API 28.
Gui Herzog
5

Me deparei com o mesmo problema no Android Emulator, onde tentei acessar um URL HTTPS externo com um certificado válido. Mas a busca desse URL no react-native falhou

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

1) Para descobrir o erro exato nos logs, ativei primeiro 'Debug JS Remotamente' usando Cmd + M no aplicativo

2) O erro relatado foi

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

3) Adicionei o certificado válido da URL usando este método -> ETAPA 2

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

Este certificado é adicionado à guia Usuário.

4) Adicione o atributo android:networkSecurityConfigattribute ao AndroidManifest.xml

Adicionar um arquivo de configuração de segurança de rede 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>

Isso deve funcionar e fornecer uma resposta esperada.

henryoats
fonte
Eu só precisava fazer o passo 4 para funcionar. Obrigado!
Bruno Serrano
4

Eu estava tendo esse problema no Android-

URL- localhost / authToken.json - não funcionou :(

URL- 10.106.105.103/authToken.json - não funcionou :(

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

Nota- Use ifconfigno Linux ou ipconfigno Windows para encontrar a máquina IpAddress

Varun Kumar
fonte
4

Para usuário do Android:

  1. Substitua localhosts por endereços IP de uma LAN porque, quando você executa o projeto em um dispositivo Android, o host local está apontando para o dispositivo Android, em vez do computador, por exemplo: mude http://localostparahttp://192.168.1.123

  2. Se o URL da sua solicitação for HTTPS e o seu dispositivo Android estiver sob um proxy, suponha que você tenha instalado uma CA adicionada pelo usuário (como a CA do burp suite ou a CA de Charles) no seu dispositivo Android, verifique se a versão do Android está abaixo do Nougat (7.0) , porque : Alterações nas autoridades de certificação confiáveis ​​no Android Nougat

    CAs adicionadas pelo usuário A
    proteção de todos os dados do aplicativo é uma das principais metas da área restrita do aplicativo Android. O Android Nougat altera a maneira como os aplicativos interagem com as CAs fornecidas pelo usuário e pelo administrador. Por padrão, os aplicativos que têm como alvo o nível 24 da API - por padrão - não respeitam essas CAs, a menos que o aplicativo aceite explicitamente. Essa configuração de segurança por padrão reduz a superfície de ataque de aplicativos e incentiva o manuseio consistente de dados de aplicativos baseados em arquivos e na rede.

fangxing
fonte
3

Para Android, você pode ter esquecido de adicionar permissão no AndroidManifest.xml É necessário adicionar a seguinte permissão.

<uses-permission android:name="android.permission.INTERNET" /> 
Shashwat
fonte
Eu já tenho isso, apesar de estar recebendo esse erro, existe alguma outra solução alternativa?
Masud_moni
@masud_moni você encontra uma maneira de resolver o problema? im ainda tendo o mesmo problema
Rafael RotiRoti
@RafaelRotiroti sim, eu resolvi esse problema, mas, embora tenha sido um tempo, é difícil lembrar, se você usou a permissão e ainda enfrenta problemas, compartilhe detalhes. Vou tentar o meu melhor para ajudar, e você terá outros também de olhar para ele
masud_moni
@masud_moni obrigado, eu corrigi esse problema usando o ip fornecido após executar o comando ifconfig. O AVD cria um dispositivo virtual, portanto, usando a mesma teoria que as máquinas virtuais que não são hospedadas em 127.0.0.1 no meu dispositivo. Então eu uso 192.168 IP e tudo funciona bem
Rafael RotiRoti
2

Eu tenho um problema semelhante. No meu caso, as solicitações para o host local estavam funcionando e de repente pararam. Acontece que o problema era que eu estava desligando meu wifi no meu telefone Android.

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

Isso funcionou para mim, o Android usa um tipo especial de endereço IP 10.0.2.2 e número da porta

import { Platform } from 'react-native';

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

se você usar janela de encaixe para a API REST, um caso de trabalhar para mim era substituir hostname: http://demo.test/apicom o endereço IP da máquina: http://x.x.x.x/api. Você pode obter o IP verificando qual ipv4 você tem na sua rede sem fio. Você também deve ter o wifi do telefone.

Craciun Ciprian
fonte
1

Você deve manipular o caso de erro em .then para buscar a API.

Por exemplo:

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
fonte
0
  1. Adicione android:usesCleartextTraffic="true"linha no AndroidManifest.xml.

  2. Exclua todas as pastas de depuração da sua pasta Android.

devkrkanhaiya
fonte
0

Você pode lidar com isso usando este:

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

Só você tem alterações na busca ....

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

Para dispositivos Android, acesse a pasta raiz do projeto e execute o comando:

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

por exemplo, adb reverse tcp:8088 tcp:8088

Isso fará com que seu dispositivo físico (por exemplo, telefone Android) ouça o servidor localhost em execução na sua máquina de desenvolvimento (ou seja, o seu computador) no endereço http: // localhost: [your_own_server_port] .

Depois disso, você pode usar diretamente http:localhost:[your_port] /your_apiem sua fetch(chamada react-native ).

Preetam Keshari Nahak
fonte
-1

Para o Android, adicione android: networkSecurityConfig = "@ xml / network_security_config" à tag do aplicativo no AndroidManifest.xml, assim:

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

conteúdo do arquivo 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
fonte
você poderia elaborar e explicar em detalhes? Eu só estou curioso como isso funciona?
ganeshdeshmukh
Modificaram o comentário, espero que ajude #
xyz
-5

Exemplo:

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