ตอบสนองการดึงข้อมูลดั้งเดิม () คำขอเครือข่ายล้มเหลว


146

เมื่อฉันสร้างแบรนด์โครงการใหม่โดยใช้react-native init(RN รุ่น 0.29.1) และใส่ดึงข้อมูลในการแสดงผลวิธีการไปยัง Facebook สาธารณะภาพยนตร์สาธิต API 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 และฉันคิดว่ามันใช้การเชื่อมต่ออินเทอร์เน็ตของคอมพิวเตอร์ของฉัน
Alek Hurst

ลองโหลดเครื่องมือจำลองด้วยตนเองและเปิด URL ในซาฟารี
FuzzyTree

5
http-> https(หากเป็นไปได้) จะแก้ไขปัญหาของคุณได้มากที่สุด
Nick Zuber

1
ฉันใช้ไอพี192.168.1.25:3000จากifconfigโดยไม่ผูกเซิร์ฟเวอร์ของฉันกับไอพีนั้นrails server --binging=192.168.1.25 --port=3000
Fabrizio

1
ใช่ฉันพยายามทั้งหมด ไม่มีอะไรทำงานให้ฉัน
Vigneswaran

คำตอบ:


140

ปัญหาที่นี่คือ iOS ไม่อนุญาตการร้องขอ HTTP ตามค่าเริ่มต้นเฉพาะ HTTPS หากคุณต้องการเปิดใช้งานคำขอ HTTP ให้เพิ่มสิ่งนี้ในinfo.plist:

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

2
คำตอบนี้ใช้ได้สำหรับฉัน สำหรับผู้อื่นที่ยังไม่คุ้นเคยกับ React Native ไฟล์นี้ (info.plist) สามารถแก้ไขได้ผ่าน xcode: stackoverflow.com/a/38219454/1299792
Marklar

86
แล้ว Android ล่ะ ฉันกำลังเผชิญกับปัญหาเดียวกันใน Android เช่นกัน
Vijay Sharma

16
เผง ใครมีคำตอบสำหรับ android?
Zach Cook

1
เมื่อฉันวางไว้บน ios / build / info.plist และรัน: react-native run-ios ios / build / info.plist ถูกเขียนทับและออกจากการเปลี่ยนแปลงของฉันฉันควรทำอย่างไร
Jorge Wander Santana Ureña

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
แล้ว Android ล่ะ
arisalexis

3
ดูเหมือนว่าจะมีไฟล์ info.plist หลายไฟล์ในหลายไดเรกทอรีในแอป React Native ของฉัน มีความคิดว่าโฟลเดอร์ใดที่มีไฟล์ที่ถูกต้องที่จะเปลี่ยน?
Marklar

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

ถ้าฉันใช้โลคัลโฮสต์ของฉันที่นี่: <key> yourserver.com </key> เมื่อพร้อมแล้วฉันพร้อมที่จะเผยแพร่ฉันจะต้องเปลี่ยนแปลงใช่ไหม
Anayo Oleru

36

ฉันใช้localhostที่อยู่ซึ่งเห็นได้ชัดว่าผิด หลังจากแทนที่ด้วยที่อยู่ IP ของเซิร์ฟเวอร์ (ในเครือข่ายที่จำลอง) มันทำงานได้อย่างสมบูรณ์

แก้ไข

ใน Android Emulator 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: //" มิฉะนั้นมันจะใช้งานไม่ได้ ... กำลังสงสัยว่าทำไมมันถึงใช้ได้กับบุรุษไปรษณีย์ แต่ไม่สามารถดึงกลับมาได้
Moucheg

@Mahmoodvcs คำตอบของคุณช่วยฉันได้มากขอบคุณมากฉันใช้ android emulator
Pena Pintada

14

สำหรับเรามันเป็นเพราะเรากำลังอัปโหลดไฟล์และ RN filePicker ไม่ได้ให้ประเภท mime ที่เหมาะสม มันให้ 'ภาพ' กับเราเป็นประเภท เราจำเป็นต้องเปลี่ยนเป็น 'รูปภาพ / jpg' เพื่อให้สามารถทำงานได้

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

@JhanhanSantana คุณอาจจะดูข้อมูลภาพดิบและได้รับมันตั้งแต่ต้น แต่ตัวเลือกพื้นเมืองตอบสนองกลับมา 'ภาพ' สำหรับฉัน
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>

ตอบโต้ Native Documents -> การรวมกับแอพที่มีอยู่ -> ทดสอบการรวมของคุณ -> เพิ่มข้อยกเว้นความปลอดภัยของการขนส่งแอพ


9

ปัญหาอาจอยู่ในการกำหนดค่าเซิร์ฟเวอร์

Android 7.0 มีข้อผิดพลาดที่อธิบายไว้ที่นี่ วิธีแก้ปัญหาที่เสนอโดย Vicky Chijwani:

กำหนดค่าเซิร์ฟเวอร์ของคุณเพื่อใช้เส้นโค้งวงรี Prime256v1 ตัวอย่างเช่นใน Nginx 1.10 คุณทำได้โดยการตั้งค่า ssl_ecdh_curve prime256v1


7

ฉันพบปัญหาเดียวกันบน Android แต่ฉันพยายามหาวิธีแก้ปัญหา Android กำลังบล็อกการรับส่งข้อความธรรมดา (ไม่ใช่คำขอ https) ตั้งแต่ระดับ API 28 โดยค่าเริ่มต้น อย่างไรก็ตาม react-native เพิ่ม network-security-config ให้กับ debug version ( 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: 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) เพื่อค้นหาข้อผิดพลาดที่แน่นอนในบันทึกฉันเปิดใช้งาน 'Debug JS Remotely' เป็นครั้งแรกโดยใช้ 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

เพิ่มไฟล์ Network Security Configuration 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 เพื่อที่จะทำงาน ขอบคุณ!
Bruno Serrano

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 ของ Lan เนื่องจากเมื่อคุณรันโครงการบนอุปกรณ์ Android localhost จะชี้ไปที่อุปกรณ์ Android แทนคอมพิวเตอร์ของคุณตัวอย่างเช่นเปลี่ยนhttp://localostเป็นhttp://192.168.1.123

  2. หาก URL คำขอของคุณคือ HTTPS และอุปกรณ์ Android ของคุณอยู่ภายใต้พร็อกซีสมมติว่าคุณได้ติดตั้ง CA ที่ผู้ใช้เพิ่ม (เช่น CA หรือ Charles's CA) ของ burp suite ในอุปกรณ์ Android ของคุณตรวจสอบให้แน่ใจว่าเวอร์ชั่น Android ของคุณนั้นต่ำกว่าNougat (7.0)เนื่องจาก : การเปลี่ยนแปลงผู้ออกใบรับรองที่เชื่อถือได้ใน Android Nougat


    การป้องกันCA ที่ผู้ใช้เพิ่มของข้อมูลแอปพลิเคชันทั้งหมดเป็นเป้าหมายหลักของแซนด์บ็อกซ์แอปพลิเคชัน Android Android Nougat เปลี่ยนวิธีที่แอปพลิเคชันโต้ตอบกับ CA ของผู้ใช้และผู้ดูแลระบบ ตามค่าเริ่มต้นแอปที่กำหนดเป้าหมายระดับ API 24 จะ - โดยการออกแบบ - ไม่ให้เกียรติ CA ดังกล่าวเว้นแต่ว่าแอพจะเปิดใช้งานอย่างชัดเจนการตั้งค่าที่ปลอดภัยโดยค่าเริ่มต้นนี้จะลดพื้นผิวการโจมตีแอปพลิเคชัน


3

สำหรับ Android คุณอาจพลาดการเพิ่มสิทธิ์ใน AndroidManifest.xml จำเป็นต้องเพิ่มการอนุญาตต่อไปนี้

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

ฉันมีอยู่แล้วถึงแม้ว่าฉันจะได้รับข้อผิดพลาดนั้นมีวิธีแก้ไขอื่น ๆ อีกไหม?
masud_moni

@masud_moni คุณหาวิธีในการแก้ไขปัญหาหรือไม่ ฉันยังคงมีปัญหาเดียวกัน
Rafael Rotiroti

@RafaelRotiroti ใช่ฉันแก้ไขปัญหานั้นแล้ว แต่แม้ว่าจะไม่นานก็ยากที่จะจำได้ถ้าคุณใช้สิทธิ์และยังประสบปัญหาอยู่โปรดแชร์รายละเอียด ฉันจะพยายามอย่างดีที่สุดเพื่อช่วยและคุณจะมีคนอื่นให้ดูด้วย
masud_moni

@masud_moni ขอบคุณฉันได้แก้ไขปัญหานั้นโดยใช้ IP ที่ระบุหลังจากรันคำสั่ง ifconfig AVD สร้างอุปกรณ์เสมือนดังนั้นใช้ทฤษฎีเดียวกันกับเครื่องเสมือนที่ไม่มีอะไรโฮสต์ใน 127.0.0.1 ในอุปกรณ์ของฉัน ดังนั้นฉันจึงใช้ IP 192.168.xx IP และทุกอย่างทำงานได้ดีเช่นกัน
Rafael Rotiroti

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

ถ้าคุณใช้นักเทียบท่าสำหรับ API ส่วนที่เหลือเป็นกรณีที่ทำงานสำหรับฉันคือการเปลี่ยนชื่อโฮสต์: http://demo.test/apiมีที่อยู่เครื่อง http://x.x.x.x/apiIP: คุณสามารถรับ IP จากการตรวจสอบว่าคุณมี ipv4 ในเครือข่ายไร้สายของคุณ คุณควรมี wifi จากโทรศัพท์ด้วย


1

คุณควรจัดการกรณีข้อผิดพลาดใน. แล้วเรียก 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. ลบโฟลเดอร์ debug ทั้งหมดออกจากโฟลเดอร์ 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][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>

คุณช่วยอธิบายรายละเอียดและอธิบายรายละเอียดได้ไหม? ฉันแค่อยากรู้ว่ามันทำงานอย่างไร
ganeshdeshmukh

ได้แก้ไขความคิดเห็นหวังว่าจะช่วยได้
xyz

-5

ตัวอย่าง:

return fetch('http://<your ip>')
  .then((response) => response.json())
  .then((responseJson) => {
    console.log(responseJson)
  })
  .catch((error) => {
    console.error(error);
  });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.