Помилка запиту на реакцію на Native ()


146

Коли я створюю новий проект з використанням react-native init(RN версії 0.29.1) та поставити вибірки в методі візуалізації для громадськості facebook демо кіно API, він кидає Network Request Failed. Існує дуже марний слід стека, і я не можу налагоджувати мережеві запити в хромованій консолі. Ось вибір, який я надсилаю:

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

1
Я не впевнений. Я використовую тренажер iOS, і я думав, що він використовує підключення до Інтернету свого комп'ютера
— Алек Херст

Спробуйте завантажити тренажер вручну та відкрити URL-адресу в сафарі
— FuzzyTree

5
http-> https(якщо можливо), швидше за все, вирішить вашу проблему
— Нік Зубер

1
Я використовував ip 192.168.1.25:3000від, ifconfigне прив'язуючи свій сервер до цього iprails server --binging=192.168.1.25 --port=3000
— Fabrizio Bertoglio

1
Так, я спробував все. Нічого не працювало для мене
— Vigneswaran A

Відповіді:


140

Проблема тут полягає в тому, що iOS не дозволяє HTTP-запити за замовчуванням, лише HTTPS. Якщо ви хочете ввімкнути HTTP-запити, додайте це до свого info.plist:

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

2
Ця відповідь спрацювала на мене. Для інших нових зреагувати Native, цей файл (info.plist) також можна редагувати з допомогою Xcode: stackoverflow.com/a/38219454/1299792
— Marklar

86
що з андроїдом? Я стикаюся з тією ж проблемою і в android.
— Віджай Шарма

16
Саме так. Хтось має відповідь на андроїд?
— Зак Кук

1
коли я ставлю це на ios / build / info.plist та запускаю: react-native run-ios Переміщений ios / build / info.plist перезаписаний та закрий мої зміни Що мені робити?
— Хорхе Вандер Сантана Уренья

1
@ JorgeWanderSantanaUreña змінити [your_project_folder_name] / ios / [your_project_folder_name] / In‌ fo.plist
— kgosse

58

Не рекомендується дозволяти всі домени для http. Зробіть виняток лише для необхідних доменів.

Джерело: Налаштування винятків безпеки транспорту додатків у iOS 9 та OSX 10.11

Додайте до файлу info.plist програми:

<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
що з андроїдом?
— arisalexis

3
Здається, у моєму додатку React Native є декілька файлів info.plist у кількох каталогах. Будь-яка ідея, яка папка містить правильний файл, який потрібно змінити?
— Marklar

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

якщо я використовую свій localhost тут: <key> yourserver.com </key>, коли я готовий до публікації, мені потрібно буде змінити його, правильно?
— Анайо Олеру

36

Я використовував localhostадресу, що, очевидно, було неправильним. Замінивши його IP-адресою сервера (у мережі, в якій є емулятор), він працював чудово.

Редагувати

В Android Emulator адреса машини для розробки 10.0.2.2. Більше пояснення тут

Для Genymotion адреса є 10.0.3.2. Більше інформації тут


4
Дякую. Напевно, єдина відповідь, яку я бачив, працює на андроїд. Використовується IP-адреса моєї мережі, і вона працює. наприкладhttp://<Network IP emulator connects to>:<port where API is served>/api/tasks
— Брендон Бенефілд

1
Не забувайте про "http: //", інакше він не працюватиме ... цікавилося, чому це буде працювати на листоноші, але не з
— фейчем

@Mahmoodvcs Ваша відповідь мені дуже допомагає, дуже дякую, я використовую емулятор Android.
— Pena

14

Для нас це було тому, що ми завантажували файл, а RN-файлPicker не надав належного типу mime. Це просто дало нам "образ" як тип. Нам потрібно було змінити його на "image / jpg", щоб змусити роботу працювати.

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

@JohhanSantana Ви, напевно, могли переглядати необроблені дані зображення і отримувати їх з самого початку, але реактивний інструмент для вибору просто повернувся для мене "зображенням".
— NickJ

10

Відповідь на це дає React Native Docs.

Apple заблокувала неявну завантаження ресурсів HTTP ясного тексту. Тому нам потрібно додати наступний файл Info.plist нашого проекту (або еквівалентний) нашого проекту.

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

React Native Docs -> Інтеграція з існуючими програмами -> Перевірте інтеграцію -> Додати виняток безпеки транспортного забезпечення додатків


9

Проблема може бути в налаштуваннях сервера.

Android 7.0 має помилку, описану тут . Запропонований рішенням Вікі Чівані:

Налаштуйте ваш сервер для використання еліптичної кривої prime256v1. Наприклад, у Nginx 1.10 ви робите це, встановлюючи ssl_ecdh_curve prime256v1;


7

У мене виникла та ж проблема на Android, але мені вдалося знайти рішення. Android блокує трафік прозорого тексту (не-https-запити), оскільки рівень API 28 за замовчуванням. Однак натискання реакцій додає мережеву безпеку-конфігурацію до версії налагодження ( android/app/src/debug/res/xml/react_native_config.xml), яка визначає деякі домени (localhost та хост-IP-адреси для AVD / Genymotion), які можна використовувати без SSL в режимі розробки. Ви можете додати свій домен туди, щоб дозволити 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>

Це працювало для мене з реакцією на рідну 0,59 та цільовою sdk 28 :)
— sameera madushan

7

Я отримав ту ж проблему на Android 9 через "http" і проблему вирішено просто додаванням андроїда: usesCleartextTraffic = "true" в 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
Дякую, це працювало і для мене. Це відбувається тому, що Android більше не підтримує HTTP за замовчуванням в API 28.
— Gui Herzog

5

Я натрапив на цю ж проблему на Android Emulator, де спробував отримати доступ до зовнішньої URL-адреси HTTPS з дійсним сертифікатом. Але отримати цю URL-адресу в реальній реакції не вдалося

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

1) Щоб дізнатися точну помилку в журналах, я спершу ввімкнув "Налагодження JS віддалено" за допомогою Cmd + M у додатку

2) Повідомлена помилка була

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

3) Я додав дійсний сертифікат URL за допомогою цього методу -> КРОК 2

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

Цей сертифікат додається на вкладку Користувач.

4) Додайте атрибут android:networkSecurityConfigатрибута до AndroidManifest.xml

Додайте файл налаштування мережевої безпеки 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>

Це має спрацювати і дати очікуваний відгук.


Мені просто потрібно було зробити крок 4, щоб працювати. Дякую!
— Бруно Серрано

4

У мене була ця проблема для Android-

URL- localhost / authToken.json - не працює :(

URL- 10.106.105.103/authToken.json - не працює :(

URL- http://10.106.105.103/authToken.json - працював :): D

Примітка. Використовуйте ifconfigв Linux або ipconfigWindows, щоб знайти машинний IpAddress


4

Для користувача Android:

  1. Замініть localhosts на IP-адреси Лана, оскільки коли ви запускаєте проект на пристрої Android, localhost вказує на пристрій Android, а не на комп'ютер, наприклад: змінити http://localostнаhttp://192.168.1.123

  2. Якщо у вашій URL-адресі запиту є HTTPS, а ваш пристрій Android знаходиться під проксі-сервером, припустімо, що на вашому пристрої Android встановлено доданий користувачем CA (наприклад, Burp suite CA або Charles's CA), переконайтеся, що версія Android знаходиться нижче Nougat (7.0) , оскільки : Зміни довірених авторизованих сертифікатів в Android Nougat


    Захищені ЦА захист усіх даних програм є ключовою метою пісочної програми Android. Android Nougat змінює взаємодію програм на взаємодії з ОС, що надаються користувачем та адміністратором. За замовчуванням програми, які орієнтуються на рівень API 24, - за задумом - не вшановуватимуть таких ЦА, якщо програма явно не включить. Цей параметр безпечного за замовчуванням зменшує поверхню атаки додатків та заохочує послідовну обробку даних мережевих та файлових програм.


3

Для Android, можливо, ви пропустили додати дозвіл в AndroidManifest.xml Потрібно додати наступний дозвіл.

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

У мене це вже є, хоча я отримую цю помилку, чи є якесь інше рішення?
— masud_moni

@masud_moni ви знайдете спосіб вирішити проблему? У них все ще виникає така ж проблема
— Рафаель

@RafaelRotiroti Так, я вирішив це питання, але, хоча минув час, важко запам'ятати, якщо ви користувались дозволом і все ще стикаєтеся з проблемами, будь ласка, поділіться деталями. Я постараюся зробити все можливе, щоб допомогти, і у вас будуть інші, щоб також заглянути до цього
— masud_moni

@masud_moni спасибі, я вирішив цю проблему за допомогою ip, наданого після запуску ifconfig команди. AVD створює віртуальний пристрій, тому використовує ту саму теорію, що й віртуальні машини, що в моєму пристрої нічого не розміщено в 127.0.0.1. Тож я використовую IP-адрес 192.168.xx, і все працює добре
— Рафаель

2

У мене є аналогічна проблема. У моєму випадку запити до localhost працювали і раптом припинялися. Виявилося, що проблема полягала в тому, що я відключив wifi на своєму телефоні Android.


2

Це працювало для мене, а Android використовує спеціальний тип IP-адреси 10.0.2.2, а потім номер порту

import { Platform } from 'react-native';

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

1

якщо ви використовуєте докер для REST API, робочий випадок для мене повинен був замінити ім'я хоста: http://demo.test/apiз IP - адресою машини: http://x.x.x.x/api. Ви можете отримати IP, перевіривши, який у вас ipv4 у вашій бездротовій мережі. Ви також повинні мати Wi-Fi з телефону.


1

Вам слід обробити випадок помилки в .then для отримання API.

Наприклад:

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. Додайте android:usesCleartextTraffic="true"рядок у AndroidManifest.xml.

  2. Видаліть всю папку налагодження зі своєї папки Android.


0

Ви можете впоратися з цим:

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

Просто у вас є зміни у витязі ....

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

На пристроях Android перейдіть до кореневої папки проекту та запустіть команду:

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

наприклад, adb reverse tcp:8088 tcp:8088

Це зробить ваш фізичний пристрій (тобто телефон Android) слухати сервер localhost, який працює на вашій розроблювальній машині (тобто ваш комп'ютер) за адресою http: // localhost: [your_own_server_port] .

Після цього ви можете безпосередньо скористатися http:localhost:[your_port] /your_apiу своєму реальному fetch() дзвінку.


-1

Для android додайте android: networkSecurityConfig = "@ xml / network_security_config" в тег додатка в AndroidManifest.xml, як це:

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

Вміст файлу 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

-5

Приклад:

return fetch('http://<your ip>')
  .then((response) => response.json())
  .then((responseJson) => {
    console.log(responseJson)
  })
  .catch((error) => {
    console.error(error);
  });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.