React Native fetch () Yêu cầu mạng không thành công


145

Khi tôi tạo một dự án hoàn toàn mới bằng cách sử dụng react-native init(phiên bản RN 0.29.1) và đặt một tìm nạp trong phương thức kết xuất vào API phim demo facebook công khai, nó sẽ ném a Network Request Failed. Có một dấu vết ngăn xếp rất vô dụng và tôi không thể gỡ lỗi các yêu cầu mạng trong bảng điều khiển chrome. Đây là tìm nạp tôi đang gửi:

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

1
Tôi không chắc. Tôi đang sử dụng trình giả lập iOS và tôi nghĩ rằng nó đã sử dụng kết nối internet của máy tính của tôi
Hurst

Hãy thử tải trình giả lập bằng tay và mở url trong safari
FuzzyTree

5
http-> https(nếu có thể) rất có thể sẽ khắc phục sự cố của bạn
Nick Zuber

1
Tôi đã sử dụng ip 192.168.1.25:3000từ ifconfigmà không ràng buộc máy chủ của mình với ip đórails server --binging=192.168.1.25 --port=3000
Fabrizio Bertoglio 21/03/19

1
Có tôi đã thử tất cả. Không có gì làm việc cho tôi
Vigneswaran

Câu trả lời:


140

Vấn đề ở đây là iOS không cho phép các yêu cầu HTTP theo mặc định, chỉ có HTTPS. Nếu bạn muốn bật yêu cầu HTTP, hãy thêm điều này vào info.plist:

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

2
Câu trả lời này đã làm việc cho tôi. Đối với những người khác mới sử dụng React Native, tệp này (info.plist) cũng có thể được chỉnh sửa thông qua xcode: stackoverflow.com/a/38219454/1299792
Marklar

86
Android thì sao? Tôi cũng đang đối mặt với vấn đề tương tự trong Android.
Vijay Sharma

16
Chính xác. Bất cứ ai cũng có câu trả lời cho Android?
Zach Cook

1
Khi tôi đặt nó trên ios / build / info.plist và run: Reac -igen run-ios Các ios / build / info.plist bị ghi đè và thoát các thay đổi của tôi Tôi nên làm gì?
Jorge Wander Santana Ureña

1
@ JorgeWanderSantanaUreña sửa đổi [your_project_folder_name] / ios / [your_project_folder_name] / In‌ fo.plist
kgosse

58

Không nên cho phép tất cả các tên miền cho http. Tạo một ngoại lệ cho chỉ các lĩnh vực cần thiết.

Nguồn: Định cấu hình ngoại lệ bảo mật vận chuyển ứng dụng trong iOS 9 và OSX 10.11

Thêm phần sau vào tệp info.plist của ứng dụng của bạn:

<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
Android thì sao?
araluexis

3
Dường như có nhiều tệp info.plist trong nhiều thư mục trong ứng dụng React Native của tôi. Bất kỳ ý tưởng thư mục nào chứa tập tin chính xác để thay đổi?
Marklar

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

nếu tôi sử dụng localhost của mình tại đây: <key> mineerver.com </ key>, khi sẵn sàng tôi sẵn sàng xuất bản, tôi sẽ cần thay đổi nó, đúng không?
Anayo Oleru

36

Tôi đã sử dụng localhostcho địa chỉ, điều này rõ ràng là sai. Sau khi thay thế nó bằng địa chỉ IP của máy chủ (trong mạng mà trình giả lập), nó đã hoạt động hoàn hảo.

Biên tập

Trong Trình giả lập Android, địa chỉ của máy phát triển là 10.0.2.2. Giải thích thêm tại đây

Đối với Genymotion, địa chỉ là 10.0.3.2. Thêm thông tin ở đây


4
Cảm ơn bạn. Có lẽ là phản hồi duy nhất tôi thấy rằng hoạt động cho Android. Đã sử dụng địa chỉ IP mạng của tôi và nó hoạt động. ví dụhttp://<Network IP emulator connects to>:<port where API is served>/api/tasks
Brandon Benefield

1
Đừng quên "http: //" nếu không nó sẽ không hoạt động ... đã tự hỏi tại sao nó sẽ hoạt động trên người đưa thư mà không phải với fetch
Moucheg

@Mahmoodvcs Câu trả lời của bạn giúp tôi rất nhiều, cảm ơn bạn rất nhiều, tôi đang sử dụng trình giả lập Android.
Pena Pintada

14

Đối với chúng tôi, đó là vì chúng tôi đã tải lên một tệp và tệp RNPicker không cung cấp loại mime thích hợp. Nó chỉ cho chúng tôi "hình ảnh" là loại. Chúng tôi cần thay đổi nó thành 'image / jpg' để tải xuống hoạt động.

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

@JohhanSantana Có lẽ bạn có thể nhìn vào dữ liệu hình ảnh thô và lấy nó từ đầu, nhưng trình chọn gốc phản ứng chỉ quay lại 'hình ảnh' cho tôi.
NickJ

10

React Native Docs đưa ra câu trả lời cho điều này.

Apple đã chặn tải tài nguyên HTTP rõ ràng ẩn. Vì vậy, chúng ta cần thêm tệp Info.plist (hoặc tương đương) sau đây của dự án.

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

Phản ứng Tài liệu gốc -> Tích hợp với các ứng dụng hiện có -> Kiểm tra tích hợp của bạn -> Thêm ngoại lệ Bảo mật vận chuyển ứng dụng


9

Vấn đề có thể là trong cấu hình máy chủ.

Android 7.0 có một lỗi được mô tả ở đây . Giải pháp được đề xuất bởi Vicky Chijwani:

Định cấu hình máy chủ của bạn để sử dụng đường cong elliptic Prime256v1. Ví dụ: trong Nginx 1.10, bạn thực hiện việc này bằng cách đặt ssl_ecdh_curve Prime256v1;


7

Tôi gặp vấn đề tương tự trên Android nhưng tôi đã tìm được giải pháp cho nó. Android đang chặn lưu lượng văn bản rõ ràng (không yêu cầu https) kể từ API cấp 28 theo mặc định. Tuy nhiên, android/app/src/debug/res/xml/react_native_config.xmlReac -igen thêm cấu hình bảo mật mạng vào phiên bản gỡ lỗi ( ) xác định một số tên miền (localhost và IP máy chủ cho AVD / Genymotion), có thể được sử dụng mà không cần SSL trong chế độ dev. Bạn có thể thêm tên miền của mình ở đó để cho phép các yêu cầu 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>

Điều này làm việc với tôi với phản ứng gốc 0,59 và sdk mục tiêu 28 :)
sameera madushan

7

Tôi gặp vấn đề tương tự trên Android 9 vì "http" và vấn đề được giải quyết bằng cách chỉ cần thêm android: usedCleartextTraffic = "true" trong 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
Cảm ơn, điều này làm việc cho tôi là tốt. Điều này xảy ra vì Android không còn hỗ trợ HTTP nữa theo mặc định trên API 28.
Gui Herzog

5

Tôi đã gặp vấn đề tương tự trên Trình giả lập Android, nơi tôi đã cố gắng truy cập URL HTTPS bên ngoài bằng chứng chỉ hợp lệ. Nhưng việc tìm kiếm URL đó trong phản ứng gốc không thành công

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

1) Để tìm ra lỗi chính xác trong nhật ký, trước tiên tôi đã bật 'Gỡ lỗi JS từ xa' bằng Cmd + M trên ứng dụng

2) Lỗi được báo cáo là

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

3) Tôi đã thêm chứng chỉ hợp lệ của URL bằng phương pháp này -> BƯỚC 2

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

Chứng chỉ này được thêm vào tab Người dùng.

4) Thêm thuộc android:networkSecurityConfigtính thuộc tính vào AndroidManifest.xml

Thêm tệp cấu hình bảo mật mạng 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>

Điều này sẽ làm việc và cung cấp cho bạn một phản ứng mong đợi.


Tôi chỉ cần làm bước 4 để làm việc. Cảm ơn!
Bruno Serrano

4

Tôi đã gặp vấn đề này cho Android-

URL- localhost / authToken.json - không hoạt động :(

URL- 10.106.105.103/authToken.json - không hoạt động :(

URL- http://10.106.105.103/authToken.json - đã hoạt động :): D

Lưu ý- Sử dụng ifconfigtrên Linux hoặc ipconfigtrên Windows để tìm máy IpAddress


4

Đối với người dùng Android:

  1. Thay thế localhosts thành địa chỉ IP Lan vì khi bạn chạy dự án trên thiết bị Android, localhost sẽ trỏ đến thiết bị Android, thay vì máy tính của bạn, ví dụ: thay đổi http://localostthànhhttp://192.168.1.123

  2. Nếu URL yêu cầu của bạn là HTTPS và thiết bị Android của bạn được ủy quyền, giả sử bạn đã cài đặt CA do người dùng thêm (như CA của bộ công cụ hoặc CA của Charles) trong thiết bị Android của bạn, hãy đảm bảo rằng phiên bản Android của bạn nằm dưới Nougat (7.0) , bởi vì : Thay đổi đối với Nhà chức trách chứng chỉ tin cậy trong Android Nougat

    CA do người dùng thêm
    Bảo vệ tất cả dữ liệu ứng dụng là mục tiêu chính của hộp cát ứng dụng Android. Android Nougat thay đổi cách các ứng dụng tương tác với các CA do người dùng và quản trị viên cung cấp. Theo mặc định, các ứng dụng nhắm mục tiêu API cấp 24 sẽ được thiết kế bởi vì không tôn trọng các CA như vậy trừ khi ứng dụng hoàn toàn áp dụng. Cài đặt mặc định an toàn này làm giảm bề mặt tấn công ứng dụng và khuyến khích xử lý nhất quán dữ liệu ứng dụng dựa trên mạng và tệp.


3

Đối với Android, bạn có thể đã bỏ lỡ để thêm quyền trong AndroidManifest.xml Cần thêm quyền sau.

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

Tôi đã có điều đó mặc dù tôi nhận được lỗi đó, có cách giải quyết nào khác không?
masud_moni

@masud_moni bạn tìm cách khắc phục vấn đề? Tôi vẫn gặp vấn đề tương tự
Rafael Rotiroti

@RafaelRotiroti vâng tôi đã giải quyết vấn đề đó, nhưng mặc dù đã được một thời gian, thật khó để nhớ, nếu bạn đã sử dụng quyền và vẫn gặp phải vấn đề, vui lòng chia sẻ chi tiết. Tôi sẽ cố gắng hết sức để giúp đỡ, và bạn cũng sẽ có những người khác để xem xét nó
masud_moni

@masud_moni cảm ơn bạn, tôi đã khắc phục vấn đề đó bằng cách sử dụng ip được cung cấp sau khi chạy lệnh ifconfig. AVD tạo ra một thiết bị ảo, vì vậy sử dụng cùng một lý thuyết so với các máy ảo không có gì được lưu trữ trong 127.0.0.1 trong thiết bị của tôi. Vì vậy, tôi sử dụng IP 192.168.xx và mọi thứ cũng hoạt động tốt
Rafael Rotiroti

2

Tôi có vấn đề tương tự. Trong trường hợp của tôi, yêu cầu đến localhost đang hoạt động và đột nhiên dừng lại. Hóa ra vấn đề là tôi đã tắt wifi trên điện thoại Android.


2

Điều này làm việc với tôi, android sử dụng một loại địa chỉ IP đặc biệt 10.0.2.2 sau đó là số cổng

import { Platform } from 'react-native';

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

1

nếu bạn sử dụng docker cho REST api, trường hợp làm việc với tôi là thay thế tên máy chủ: http://demo.test/apibằng địa chỉ ip của máy : http://x.x.x.x/api. Bạn có thể lấy IP từ việc kiểm tra ipv4 nào bạn có trên mạng không dây. Bạn cũng nên có wifi từ điện thoại trên.


1

Bạn nên xử lý trường hợp lỗi trong .then để tìm nạp API.

Ví dụ:

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. Thêm android:usesCleartextTraffic="true"dòng trong AndroidManifest.xml.

  2. Xóa tất cả thư mục gỡ lỗi khỏi thư mục Android của bạn.


-1

Chỉ cần bạn có Thay đổi trong Tìm nạp ....

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

Đối với thiết bị Android, hãy chuyển đến thư mục gốc dự án của bạn và chạy lệnh:

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

ví dụ, adb reverse tcp:8088 tcp:8088

Điều này sẽ làm cho thiết bị vật lý của bạn (tức là điện thoại Android) lắng nghe máy chủ localhost chạy trên máy phát triển của bạn (tức là máy tính của bạn) trên địa chỉ http: // localhost: [your_own_server_port] .

Sau đó, bạn có thể trực tiếp sử dụng http:localhost:[your_port] /your_apitrong fetch(cuộc gọi phản ứng gốc của mình .


-1

Đối với Android, hãy thêm android: networkSecurityConfig = "@ xml / network_security_config" vào thẻ ứng dụng trong AndroidManifest.xml, như thế này:

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

Nội dung tệp 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>

bạn có thể vui lòng giải thích và giải thích chi tiết? Tôi chỉ tò mò làm thế nào nó hoạt động?
ganeshdeshmukh

Đã sửa đổi nhận xét, hy vọng điều đó sẽ giúp
xyz

-5

Thí dụ:

return fetch('http://<your ip>')
  .then((response) => response.json())
  .then((responseJson) => {
    console.log(responseJson)
  })
  .catch((error) => {
    console.error(error);
  });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.