React Native fetch () Permintaan Jaringan Gagal

146

Ketika saya membuat proyek baru menggunakan react-native init(RN versi 0.29.1) dan memasukkan metode render ke film demo facebook publik API, itu melempar a Network Request Failed. Ada jejak stack yang sangat tidak berguna dan saya tidak bisa men-debug permintaan jaringan di konsol chrome. Ini adalah pengambilan yang saya kirim:

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
sumber
1
Saya tidak yakin. Saya menggunakan simulator iOS dan saya pikir itu menggunakan koneksi internet komputer saya
Alek Hurst
Coba muat simulator secara manual dan buka url di safari
FuzzyTree
5
http-> https(jika mungkin) kemungkinan besar akan memperbaiki masalah Anda
Nick Zuber
1
Saya menggunakan ip 192.168.1.25:3000dari ifconfigtanpa mengikat server saya ke ip iturails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio
1
Ya saya sudah mencoba semua. Tidak ada yang berhasil untuk saya
Vigneswaran

Jawaban:

140

Masalahnya di sini adalah bahwa iOS tidak mengizinkan permintaan HTTP secara default, hanya HTTPS. Jika Anda ingin mengaktifkan permintaan HTTP, tambahkan ini ke info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Alek Hurst
sumber
2
Jawaban ini berhasil untuk saya. Bagi yang baru mengenal React Native, file ini (info.plist) juga dapat diedit melalui xcode: stackoverflow.com/a/38219454/1299792
Marklar
86
bagaimana dengan android? Saya menghadapi masalah yang sama di android juga.
Vijay Sharma
16
Persis. Adakah yang punya jawaban untuk android?
Zach Cook
1
ketika saya meletakkannya di ios / build / info.plist dan jalankan: react-native run-ios ios / build / info.plist ditimpa dan keluar dari perubahan saya. Apa yang harus saya lakukan?
Jorge Wander Santana Ureña
1
@ JorgeWanderSantanaUreña memodifikasi [your_project_folder_name] / ios / [your_project_folder_name] / In‌ fo.plist
kgosse
58

Tidak disarankan untuk mengizinkan semua domain untuk http. Buat pengecualian hanya untuk domain yang diperlukan.

Sumber: Mengkonfigurasi Pengecualian Keamanan Transport Aplikasi di iOS 9 dan OSX 10.11

Tambahkan berikut ini ke file info.plist aplikasi Anda:

<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
sumber
27
bagaimana dengan android?
arisalexis
3
Tampaknya ada beberapa file info.plist di beberapa direktori di aplikasi React Native saya. Adakah folder yang berisi file yang benar untuk diubah?
Marklar
2
@Marklar [your_project_folder_name] / ios / [your_project_folder_name] /Info.plist
Stich
jika saya menggunakan localhost saya di sini: <key> yourserver.com </key>, ketika siap saya siap untuk menerbitkan, saya harus mengubahnya, benarkan?
Anayo Oleru
36

Saya menggunakan localhostalamat itu, yang jelas salah. Setelah menggantinya dengan alamat IP server (di jaringan emulator itu), ia bekerja dengan sempurna.

Edit

Di Android Emulator, alamat mesin pengembangan adalah 10.0.2.2. Penjelasan lebih lanjut di sini

Untuk Genymotion, alamatnya adalah 10.0.3.2. Info lebih lanjut di sini

Mahmoodvcs
sumber
4
Terima kasih. Mungkin satu-satunya respons yang saya lihat yang berfungsi untuk android. Menggunakan alamat IP jaringan saya dan berfungsi. mishttp://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield
1
Jangan lupa "http: //" kalau tidak, itu tidak akan berhasil ... bertanya-tanya mengapa itu akan berhasil pada tukang pos tetapi tidak dengan mengambil
Moucheg
@ Mahmoodvcs Jawaban Anda banyak membantu saya, terima kasih banyak, saya menggunakan emulator android.
Pena Pintada
14

Bagi kami itu karena kami mengunggah file dan filePicker RN tidak memberikan tipe mime yang tepat. Itu hanya memberi kami 'gambar' sebagai tipenya. Kami perlu mengubahnya ke 'gambar / jpg' untuk membuat pengambilan berfungsi.

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })
NickJ
sumber
@JohhanSantana Anda mungkin bisa melihat data gambar mentah dan mendapatkannya dari awal, tetapi pemilih asli yang bereaksi baru saja kembali 'gambar' untuk saya.
NickJ
10

Bereaksi Dokumen Asli memberikan jawaban untuk ini.

Apple telah memblokir pemuatan sumber daya HTTP cleartext implisit. Jadi kita perlu menambahkan file Info.plist (atau setara) proyek berikut ini.

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

Bereaksi Dokumen Asli -> Integrasi Dengan Aplikasi yang Ada -> Uji integrasi Anda -> Tambahkan pengecualian Keamanan Transport Aplikasi

lautan
sumber
9

Masalahnya mungkin dalam konfigurasi server.

Android 7.0 memiliki bug yang dijelaskan di sini . Solusi yang diusulkan oleh Vicky Chijwani:

Konfigurasikan server Anda untuk menggunakan kurva elips prime256v1. Misalnya, di Nginx 1.10 Anda melakukan ini dengan mengatur ssl_ecdh_curve prime256v1;

Dmitry Maksakov
sumber
7

Saya mendapat masalah yang sama di Android tetapi saya berhasil menemukan solusi untuk itu. Android memblokir lalu lintas cleartext (non-https-request) sejak API Level 28 secara default. Namun, react-asli menambahkan konfigurasi keamanan jaringan ke versi debug ( android/app/src/debug/res/xml/react_native_config.xml) yang mendefinisikan beberapa domain (localhost, dan IP host untuk AVD / Genymotion), yang dapat digunakan tanpa SSL dalam mode dev. Anda dapat menambahkan domain Anda di sana untuk memungkinkan permintaan 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
sumber
Ini bekerja untuk saya dengan reaksi asli 0,59 dan target SDK 28 :)
sameera madushan
7

Saya mendapat masalah yang sama di Android 9 karena "http" dan masalah diselesaikan dengan hanya menambahkan android: usingCleartextTraffic = "true" di 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
sumber
2
Terima kasih, ini berhasil juga untuk saya. Itu terjadi karena Android tidak lagi mendukung HTTP per default pada API 28.
Gui Herzog
5

Saya menemukan masalah yang sama pada Android Emulator, di mana saya mencoba mengakses URL HTTPS eksternal dengan sertifikat yang valid. Tetapi gagal mengambil URL itu dalam bahasa asli

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

1) Untuk mengetahui kesalahan yang sebenarnya dalam log, saya pertama kali mengaktifkan 'Debug JS Remotely' menggunakan Cmd + M pada aplikasi

2) Kesalahan yang dilaporkan adalah

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

3) Saya menambahkan sertifikat URL yang valid menggunakan metode ini -> LANGKAH 2

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

Sertifikat ini ditambahkan ke tab Pengguna.

4) Tambahkan atribut android:networkSecurityConfigatribut ke AndroidManifest.xml

Tambahkan file Konfigurasi Keamanan Jaringan 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>

Ini seharusnya bekerja dan memberi Anda respons yang diharapkan.

henryoats
sumber
Saya hanya perlu melakukan langkah 4 agar dapat bekerja. Terima kasih!
Bruno Serrano
4

Saya mengalami masalah ini untuk Android-

URL- localhost / authToken.json - tidak berfungsi :(

URL- 10.106.105.103/authToken.json - tidak berfungsi :(

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

Catatan - Gunakan ifconfigdi Linux atau ipconfigdi Windows untuk menemukan mesin IpAddress

Varun Kumar
sumber
4

Untuk pengguna Android:

  1. Ganti localhosts ke alamat IP Lan karena ketika Anda menjalankan proyek pada perangkat Android, localhost menunjuk ke perangkat Android, alih-alih komputer Anda, contoh: ubah http://localostkehttp://192.168.1.123

  2. Jika URL permintaan Anda adalah HTTPS dan perangkat Android Anda berada di bawah proxy, anggap Anda telah menginstal CA yang ditambahkan Pengguna (seperti CA burp suite atau CA Charles) di perangkat Android Anda, pastikan versi Android Anda di bawah Nougat (7.0) , karena : Perubahan pada Otoritas Sertifikat Tepercaya di Android Nougat

    CA yang ditambahkan pengguna
    Perlindungan semua data aplikasi adalah tujuan utama dari kotak pasir aplikasi Android. Android Nougat mengubah cara aplikasi berinteraksi dengan CA yang disediakan pengguna dan admin. Secara default, aplikasi yang menargetkan API level 24 akan — dengan desain — tidak menghormati CA semacam itu kecuali jika aplikasi secara eksplisit memilih. Pengaturan safe-by-default ini mengurangi permukaan serangan aplikasi dan mendorong penanganan yang konsisten terhadap data aplikasi berbasis jaringan dan file.

Fangxing
sumber
3

Untuk Android, Anda mungkin telah melewatkan untuk menambahkan izin di AndroidManifest.xml Perlu menambahkan izin berikut.

<uses-permission android:name="android.permission.INTERNET" /> 
Shashwat
sumber
Saya sudah memilikinya walaupun saya mendapatkan kesalahan itu, apakah ada solusi lain?
masud_moni
@masud_moni Anda menemukan cara untuk memperbaiki masalah? Saya masih memiliki masalah yang sama
Rafael Rotiroti
@RafaelRotiroti ya saya menyelesaikan masalah itu, tetapi meskipun sudah agak lama, sulit untuk diingat, jika Anda telah menggunakan izin dan masih menghadapi masalah, silakan bagikan detailnya. Saya akan mencoba yang terbaik untuk membantu, dan Anda akan meminta orang lain untuk memeriksanya
masud_moni
@masud_moni terima kasih, saya telah memperbaiki masalah menggunakan ip yang diberikan setelah menjalankan perintah ifconfig. AVD menciptakan perangkat virtual, jadi menggunakan teori yang sama dari mesin virtual yang tidak di-host di 127.0.0.1 di perangkat saya. Jadi saya menggunakan IP 192.168.xx dan semuanya berfungsi dengan baik
Rafael Rotiroti
2

Saya punya masalah serupa. Dalam kasus saya, permintaan ke localhost berfungsi dan tiba-tiba berhenti. Ternyata masalahnya adalah saya mematikan wifi di ponsel android saya.

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

Ini bekerja untuk saya, android menggunakan tipe khusus dari alamat IP 10.0.2.2 kemudian nomor port

import { Platform } from 'react-native';

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

jika Anda menggunakan buruh pelabuhan untuk api REST, kasus yang bekerja bagi saya adalah untuk mengganti hostname: http://demo.test/apidengan mesin alamat ip: http://x.x.x.x/api. Anda bisa mendapatkan IP dari memeriksa IPv4 apa yang Anda miliki di jaringan nirkabel Anda. Anda juga harus mengaktifkan wifi dari ponsel.

Craciun Ciprian
sumber
1

Anda harus menangani kasus kesalahan di. Kemudian untuk mengambil API.

Sebagai contoh:

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;
});
pengguna3374790
sumber
0
  1. Tambahkan android:usesCleartextTraffic="true"baris di AndroidManifest.xml.

  2. Hapus semua folder debug dari folder android Anda.

devkrkanhaiya
sumber
0

Anda dapat mengatasinya menggunakan ini:

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

Hanya Anda memiliki Perubahan pada Ambil ....

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

Untuk perangkat Android, buka folder root proyek Anda dan jalankan perintah:

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

misalnya, adb reverse tcp:8088 tcp:8088

Ini akan membuat perangkat fisik Anda (yaitu ponsel Android) mendengarkan server localhost yang berjalan pada mesin pengembangan Anda (yaitu komputer Anda) di alamat http: // localhost: [your_own_server_port] .

Setelah itu, Anda dapat langsung menggunakan panggilan http:localhost:[your_port] /your_apiasli-reaksi Anda fetch().

Preetam Keshari Nahak
sumber
-1

Untuk android, tambahkan android: networkSecurityConfig = "@ xml / network_security_config" ke tag aplikasi di AndroidManifest.xml, seperti ini:

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

konten 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>
xyz
sumber
bisa tolong jelaskan, dan jelaskan secara detail? Saya hanya ingin tahu bagaimana cara kerjanya?
ganeshdeshmukh
Telah mengubah komentar, harap itu akan membantu
xyz
-5

Contoh:

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