جاوااسکریپت - خطای درخواست شبکه fetch() در ریاکت نیتیو
وقتی یک پروژه کاملاً جدید با استفاده از react-native init (نسخه RN 0.29.1) ایجاد میcکنم و یک واکشی در روش رندر به API فیلم نمایشی عمومی فیسcبوک ارسال میcکنم، یک درخواست شبکه ناموفق بود رخ میcدهد. یک ردیابی پشته بسیار بی فایده وجود دارد و من نمی توانم درخواست های شبکه را در کنسول کروم اشکال زدایی کنم. این واکشی است که من می فرستم:
fetch('http://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
پاسخ شماره ۱
مشکل اینجاست که iOS به طور پیشفرض درخواستهای HTTP را مجاز نمیداند و تنها HTTPS را اجازه میدهد. اگر میخواهید درخواستهای HTTP را فعال کنید، این را به info.plist خود اضافه کنید:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
پاسخ شماره ۲
من از localhost برای آدرس استفاده میکردم، که واضح بود اشتباه است. بعد از اینکه آن را با آدرس آیپی سرور (در شبکهای که شبیهساز در آن قرار دارد) جایگزین کردم، کاملاً درست کار کرد.
ویرایش
در شبیهساز اندروید، آدرس ماشین توسعه 10.0.2.2 است. توضیحات بیشتر در اینجا
برای Genymotion، آدرس 10.0.3.2 است. اطلاعات بیشتر در اینجا
پاسخ شماره ۳
توصیه نمیشود اجازه دهید همه دامنهها برای 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>
پاسخ شماره ۴
من همین مشکل را در اندروید ۹ داشتم به خاطر "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>
پاسخ شماره ۵
برای ما این بود که ما در حال آپلود یک فایل بودیم و فایلپیکر RN نوع mime مناسب را ارائه نمیداد. فقط نوع را به صورت 'image' به ما میداد. ما نیاز داشتیم آن را به 'image/jpg' تغییر دهیم تا fetch کار کند.
form.append(uploadFileName, {
uri : localImage.full,
type: 'image/jpeg',
name: uploadFileName
})
پاسخ شماره ۶
اگر از لوکالهاست استفاده میکنید، فقط آن را تغییر دهید:
از :http://localhost:3030 به :http://10.0.2.2:3030
پاسخ شماره ۷
من همان مشکل را در اندروید داشتم اما توانستم راه حلی برای آن پیدا کنم. اندروید به طور پیشفرض از سطح API 28 به بعد، ترافیک متن ساده (درخواستهای غیر HTTPS) را مسدود میکند. با این حال، react-native یک network-security-config به نسخه دیباگ اضافه میکند (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>
پاسخ شماره ۸
برای کاربران اندروید:
تغییر
localhostها به آدرسهای IP شبکه محلی، زیرا وقتی پروژه را روی یک دستگاه اندروید اجرا میکنید، localhost به دستگاه اندروید اشاره میکند به جای کامپیوتر شما، مثال: تغییرhttp://localostبهhttp://192.168.1.123اگر URL درخواست شما HTTPS است و دستگاه اندروید شما تحت یک پروکسی است، فرض کنید CA اضافه شده توسط کاربر (مانند CA بورپ سوئیت یا CA چارلز) را در دستگاه اندروید خود نصب کردهاید، اطمینان حاصل کنید که نسخه اندروید شما پایینتر از Nougat(7.0) است، زیرا: تغییرات در مراجع صدور گواهی معتبر در اندروید Nougat
CAهای اضافه شده توسط کاربر
حفاظت از همه دادهcهای یک برنامه یک هدف کلیدی در محیط جعبه ایمنی برنامه Android است. Android Nougat نحوه تعامل برنامه ها با CA های ارائه شده توسط کاربر و سرپرست را تغییر می دهد. بهcطور پیشcفرض، برنامهcهایی که سطح 24 API را هدف قرار میcدهند - از نظر طراحی - به این CAها اعتماد ندارند، مگر اینکه برنامه بهcصراحت آن را انتخاب کند. این تنظیم ایمن سطح حمله برنامهcها را بهcطور پیشcفرض کاهش میcدهد و مدیریت یکسان دادهcهای مبتنی بر شبکه و فایل برنامه را تشویق میcکند.
پاسخ شماره ۹
مستندات React Native پاسخ این را میدهد.
اپل بارگذاری منابع HTTP متنی صریح ضمنی را مسدود کرده است. بنابراین ما نیاز داریم که موارد زیر را به فایل Info.plist پروژه خود (یا فایل معادل آن) اضافه کنیم.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
مستندات React Native -> یکپارچهسازی با برنامههای موجود -> تست یکپارچهسازی خود -> افزودن استثنای امنیت انتقال برنامه
پاسخ شماره ۱۰
ممکن است مشکل در پیکربندی سرور باشد.
اندروید ۷.۰ دارای باگی است که در اینجا توضیح داده شده است. راهحل پیشنهادی توسط ویکی چیجوانی:
سرور خود را طوری پیکربندی کنید که از منحنی بیضوی prime256v1 استفاده کند. به عنوان مثال، در Nginx 1.10 این کار را با تنظیم ssl_ecdh_curve prime256v1; انجام میدهید.
پاسخ شماره ۱۱
من این مشکل را برای اندروید داشتم
URL- localhost/authToken.json - کار نکرد :(
URL- 10.106.105.103/authToken.json - کار نکرد :(
URL- http://10.106.105.103/authToken.json - کار کرد :) :D
توجه - برای یافتن آدرس آیپی دستگاه، از ifconfig در لینوکس یا ipconfig در ویندوز استفاده کنید
