Помилка запиту на реакцію на 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.