React Native fetch () Сбой сетевого запроса


146

Когда я создаю новый проект с использованием react-native init(версия 0.29.1 RN) и помещаю выборку в метод рендеринга в общедоступный API демо-фильма Facebook, он выдает a Network Request Failed. Существует очень бесполезная трассировка стека, и я не могу отлаживать сетевые запросы в консоли Chrome. Вот выручка, которую я отправляю:

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 в
Safari

5
http-> https(если возможно), скорее всего, решит вашу проблему
Ник Цубер

1
Я использовал внутрибрюшинно 192.168.1.25:3000из ifconfigбез привязки моего сервера к этому IPrails server --binging=192.168.1.25 --port=3000
Фабрицио Bertoglio

1
Да я все перепробовал. У меня
ничего не получалось

Ответы:


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 и запускаю: response-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 в нескольких каталогах. Любая идея, какая папка содержит правильный файл для изменения?
Марклар

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

если я использую свой локальный хост здесь: <key> yourserver.com </ key>, когда я буду готов опубликовать, мне нужно его изменить, правильно?
Анаё Олеру

36

Я использовал localhostдля адреса, который был явно неправ. После замены его на IP-адрес сервера (в сети, в которой находится эмулятор), все заработало отлично.

редактировать

В эмуляторе Android адрес машины для разработки есть 10.0.2.2. Больше объяснений здесь

Для Genymotion, адрес есть 10.0.3.2. Больше информации здесь


4
Спасибо. Вероятно, единственный ответ, который я видел, который работает для Android. Использовал мои сети по IP-адресу и все работает. напр.http://<Network IP emulator connects to>:<port where API is served>/api/tasks
Брэндон Бенефилд,

1
Не забывайте "http: //", иначе он не будет работать ... Интересно, почему он будет работать с почтальоном, а не с fetch
Moucheg

@Mahmoodvcs Ваш ответ мне очень помог, большое спасибо, я использую эмулятор Android.
Пена Пинтада

14

Для нас это было потому, что мы загружали файл, а RN filePicker не давал правильный тип пантомимы. Это просто дало нам «образ» как тип. Нам нужно было изменить его на «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>

Реагирование на собственные документы -> Интеграция с существующими приложениями -> Проверка интеграции -> Добавить исключение безопасности транспорта приложения


9

Проблема может быть в конфигурации сервера.

В Android 7.0 есть ошибка, описанная здесь . Временное решение, предложенное Вики Chijwani:

Сконфигурируйте свой сервер для использования эллиптической кривой prime256v1. Например, в Nginx 1.10 вы делаете это, устанавливая ssl_ecdh_curve prime256v1;


7

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

5

Я столкнулся с той же проблемой в эмуляторе Android, где пытался получить доступ к внешнему 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 Remote», используя 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 или ipconfigв Windows, чтобы найти IpAddress компьютера.


4

Для пользователя Android:

  1. Замените localhosts на IP-адреса Lan, потому что при запуске проекта на устройстве Android localhost указывает на устройство Android, а не на компьютер, например: измените http://localostнаhttp://192.168.1.123

  2. Если URL-адрес вашего запроса - HTTPS, а ваше Android-устройство использует прокси-сервер, предположим, что на вашем Android-устройстве установлен CA, добавленный пользователем (например, CA от Burp Suite или Charles's), убедитесь, что ваша версия Android ниже Nougat (7.0) , поскольку : Изменения в доверенных центрах сертификации в Android Nougat

    CA, добавленные пользователем
    Защита всех данных приложений является ключевой целью изолированной программной среды приложений 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 на моем устройстве. Так что я использую 192.168.xx IP, и все также отлично работает
Рафаэль Ротироти

2

У меня похожая проблема. В моем случае запросы к localhost работали и внезапно прекратились. Оказалось, что проблема была в том, что я отключил свой Wi-Fi на моем телефоне 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 ....

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.