Fetch API

هذا الدرس التطبيقي حول الترميز هو جزء من الدورة التدريبية "تطوير تطبيقات الويب التقدّمية" التي طوّرها فريق التدريب في "مطوّرو Google". ستستفيد إلى أقصى حدّ من هذه الدورة التدريبية إذا عملت على إكمال دروس الترميز بالتسلسل.

للاطّلاع على التفاصيل الكاملة حول الدورة التدريبية، يُرجى الانتقال إلى نظرة عامة على تطوير تطبيقات الويب التقدّمية.

مقدمة

يرشدك هذا المختبر إلى كيفية استخدام Fetch API، وهي واجهة بسيطة لجلب الموارد، وهي تحسين على واجهة XMLHttpRequest API.

أهداف الدورة التعليمية

  • كيفية استخدام Fetch API لطلب الموارد
  • كيفية تقديم طلبات GET وHEAD وPOST باستخدام fetch
  • كيفية قراءة العناوين المخصّصة وتحديدها
  • استخدام سياسة مشاركة الموارد متعددة المصادر (CORS) وقيودها

ما يتعين عليك معرفته

  • أساسيات JavaScript وHTML
  • الإلمام بمفهوم Promises في ES2015 وبنيته الأساسية

المتطلبات

  • جهاز كمبيوتر يمكن الوصول إلى واجهة النظام أو المحطة الطرفية فيه
  • الاتصال بالإنترنت
  • متصفّح متوافق مع Fetch
  • محرّر نصوص
  • Node وnpm

ملاحظة: على الرغم من أنّ Fetch API غير متوافق حاليًا مع جميع المتصفّحات، يتوفّر polyfill.

نزِّل مستودع pwa-training-labs أو استنسِخه من GitHub وثبِّت إصدار LTS من Node.js، إذا لزم الأمر.

افتح سطر الأوامر على الكمبيوتر. انتقِل إلى الدليل fetch-api-lab/app/ وابدأ خادم تطوير محليًا:

cd fetch-api-lab/app
npm install
node server.js

يمكنك إيقاف الخادم في أي وقت باستخدام Ctrl-c.

افتح المتصفّح وانتقِل إلى localhost:8081/. من المفترض أن تظهر لك صفحة تتضمّن أزرارًا لتقديم الطلبات (لن تعمل هذه الأزرار بعد).

ملاحظة: ألغِ تسجيل أي مشغّلات خدمات وامحُ جميع ذاكرات التخزين المؤقت لمشغّلات الخدمات في localhost لكي لا تتداخل مع المختبر. في "أدوات مطوّري البرامج في Chrome"، يمكنك إجراء ذلك من خلال النقر على محو بيانات الموقع الإلكتروني من قسم محو مساحة التخزين في علامة التبويب التطبيق.

افتح المجلد fetch-api-lab/app/ في محرِّر النصوص الذي تفضّله. المجلد app/ هو المكان الذي ستنشئ فيه المختبر.

يحتوي هذا المجلد على ما يلي:

  • يحتوي echo-servers/ على ملفات تُستخدَم لتشغيل خوادم الاختبار
  • يحتوي examples/ على نماذج للموارد التي نستخدمها في تجربة عملية الجلب
  • js/main.js هو ملف JavaScript الرئيسي للتطبيق، وهو المكان الذي ستكتب فيه كل الرموز البرمجية
  • index.html هي صفحة HTML الرئيسية للموقع الإلكتروني/التطبيق النموذجي
  • package-lock.json وpackage.json هما ملفا إعداد لخادم التطوير وتبعيات خادم الصدى
  • server.js هو خادم تطوير العُقدة

تتضمّن واجهة برمجة التطبيقات Fetch واجهة بسيطة نسبيًا. يوضّح هذا القسم كيفية كتابة طلب HTTP أساسي باستخدام fetch.

استرداد ملف JSON

في js/main.js، يتم ربط زر استرداد JSON الخاص بالتطبيق بالدالة fetchJSON.

عدِّل الدالة fetchJSON لطلب الملف examples/animals.json وتسجيل الردّ:

function fetchJSON() {
  fetch('examples/animals.json')
    .then(logResult)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد JSON. يجب أن تسجّل وحدة التحكّم استجابة عملية الجلب.

الشرح

يقبل الأسلوب fetch مسار المرجع الذي نريد استرداده كمَعلمة، وهو examples/animals.json في هذه الحالة. تعرض الدالة fetch وعدًا يتم تنفيذه إلى كائن استجابة. إذا تم تنفيذ الوعد، يتم تمرير الرد إلى الدالة logResult. إذا تم رفض الوعد، تتولّى catch المهمة ويتم تمرير الخطأ إلى الدالة logError.

تمثّل عناصر الاستجابة الردّ على طلب. تحتوي هذه الكائنات على نص الاستجابة بالإضافة إلى خصائص وطُرق مفيدة.

اختبار الردود غير الصالحة

افحص الاستجابة المسجّلة في وحدة التحكّم. لاحظ قيم السمات status وurl وok.

استبدِل المرجع examples/animals.json في fetchJSON بـ examples/non-existent.json. من المفترض أن تبدو الدالة fetchJSON المعدَّلة الآن على النحو التالي:

function fetchJSON() {
  fetch('examples/non-existent.json')
    .then(logResult)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد JSON مرة أخرى لمحاولة استرداد هذا المرجع غير المتوفّر.

لاحظ أنّ عملية الجلب اكتملت بنجاح، ولم تؤدِّ إلى تشغيل الحظر catch. ابحث الآن عن السمات status وURL وok للإجابة الجديدة.

يجب أن تكون القيم مختلفة في الملفَّين (هل تعرف السبب؟). إذا تلقّيت أي أخطاء في وحدة التحكّم، هل تتطابق القيم مع سياق الخطأ؟

الشرح

لماذا لم يؤدِّ الردّ الذي تعذّر إرساله إلى تفعيل الحظر catch؟ هذه ملاحظة مهمة بشأن عمليات الجلب والوعود، إذ إنّ الردود غير الصالحة (مثل الردود من النوع 404) لا تزال قابلة للحلّ. لا يتم رفض وعد الجلب إلا إذا تعذّر إكمال الطلب، لذا عليك دائمًا التحقّق من صحة الردّ. سنتأكّد من صحة الردود في القسم التالي.

لمزيد من المعلومات

التحقّق من صحة الردّ

علينا تعديل الرمز البرمجي للتحقّق من صحة الردود.

في main.js، أضِف دالة للتحقّق من صحة الردود:

function validateResponse(response) {
  if (!response.ok) {
    throw Error(response.statusText);
  }
  return response;
}

بعد ذلك، استبدِل fetchJSON بالرمز التالي:

function fetchJSON() {
  fetch('examples/non-existent.json')
    .then(validateResponse)
    .then(logResult)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد JSON. تحقَّق من وحدة التحكّم. الآن، يجب أن يؤدي الردّ على examples/non-existent.json إلى تشغيل المجموعة catch.

استبدِل examples/non-existent.json في الدالة fetchJSON بالدالة الأصلية examples/animals.json. من المفترض أن تبدو الدالة المعدَّلة الآن على النحو التالي:

function fetchJSON() {
  fetch('examples/animals.json')
    .then(validateResponse)
    .then(logResult)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد JSON. من المفترض أن تلاحظ أنّه يتم تسجيل الردّ بنجاح كما كان يحدث من قبل.

الشرح

بعد إضافة validateResponse check، ستؤدي الاستجابات السيئة (مثل 404) إلى ظهور خطأ وستتولى catch المهمة. يتيح لنا ذلك التعامل مع الردود غير الناجحة ويمنع انتشار الردود غير المتوقّعة في سلسلة عمليات الجلب.

قراءة الرد

يتم تمثيل استجابات الجلب على شكل ReadableStreams (مواصفات البث)، ويجب قراءتها للوصول إلى نص الاستجابة. تحتوي عناصر الرد على طُرق لإجراء ذلك.

في main.js، أضِف الدالة readResponseAsJSON مع الرمز التالي:

function readResponseAsJSON(response) {
  return response.json();
}

بعد ذلك، استبدِل الدالة fetchJSON بالرمز التالي:

function fetchJSON() {
  fetch('examples/animals.json') // 1
  .then(validateResponse) // 2
  .then(readResponseAsJSON) // 3
  .then(logResult) // 4
  .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد JSON. تحقَّق من وحدة التحكّم للتأكّد من أنّه يتم تسجيل JSON من examples/animals.json (بدلاً من عنصر الاستجابة).

الشرح

لنراجع ما يحدث.

الخطوة 1: يتم استدعاء عملية الجلب على أحد الموارد، examples/animals.json. تعرض الدالة Fetch وعدًا يتم تنفيذه إلى عنصر Response. عندما يتم حلّ الوعد، يتم تمرير عنصر الاستجابة إلى validateResponse.

الخطوة 2: تتحقّق validateResponse مما إذا كان الرد صالحًا (هل هو 200؟). إذا لم يكن الأمر كذلك، سيحدث خطأ، وسيتم تخطّي بقية كتل then وتشغيل كتلة catch. هذه الخطوة مهمة بشكل خاص. بدون هذا التحقّق، يتم تمرير الردود غير الصالحة في السلسلة، وقد يؤدي ذلك إلى إيقاف الرمز اللاحق الذي قد يعتمد على تلقّي رد صالح. إذا كانت الاستجابة صالحة، يتم تمريرها إلى readResponseAsJSON.

الخطوة 3: تعمل readResponseAsJSON على قراءة نص الاستجابة باستخدام طريقة Response.json(). تعرض هذه الطريقة وعدًا يتم تنفيذه إلى JSON. بعد أن يتم تنفيذ هذا الوعد، يتم تمرير بيانات JSON إلى logResult. (في حال رفض الوعد من response.json()، يتم تفعيل كتلة catch).

الخطوة 4: أخيرًا، يسجّل logResult بيانات JSON من الطلب الأصلي إلى examples/animals.json.

لمزيد من المعلومات

لا يقتصر Fetch على JSON. في هذا المثال، سنجلب صورة ونضيفها إلى الصفحة.

في main.js، اكتب دالة showImage باستخدام الرمز التالي:

function showImage(responseAsBlob) {
  const container = document.getElementById('img-container');
  const imgElem = document.createElement('img');
  container.appendChild(imgElem);
  const imgUrl = URL.createObjectURL(responseAsBlob);
  imgElem.src = imgUrl;
}

بعد ذلك، أضِف الدالة readResponseAsBlob التي تقرأ الردود كـ Blob:

function readResponseAsBlob(response) {
  return response.blob();
}

عدِّل الدالة fetchImage باستخدام الرمز التالي:

function fetchImage() {
  fetch('examples/fetching.jpg')
    .then(validateResponse)
    .then(readResponseAsBlob)
    .then(showImage)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد الصورة. من المفترض أن يظهر لك كلب لطيف يجلب عصا على الصفحة (هذه مزحة مرتبطة بالكلاب!).

الشرح

في هذا المثال، يتم جلب صورة، examples/fetching.jpg. كما هو الحال في التمرين السابق، يتم التحقّق من صحة الرد باستخدام validateResponse. بعد ذلك، تتم قراءة الردّ على أنّه Blob (بدلاً من JSON كما في القسم السابق). يتم إنشاء عنصر صورة وإلحاقه بالصفحة، ويتم ضبط السمة src للصورة على عنوان URL للبيانات يمثّل Blob.

ملاحظة: يتم استخدام طريقة createObjectURL() لكائن عنوان URL لإنشاء عنوان URL للبيانات يمثّل Blob. من المهم ملاحظة ذلك. لا يمكنك ضبط مصدر الصورة مباشرةً على Blob. يجب تحويل Blob إلى عنوان URL للبيانات.

لمزيد من المعلومات

هذا القسم هو تحدٍّ اختياري.

تعديل الدالة fetchText لتصبح

  1. إحضار /examples/words.txt
  2. التحقّق من صحة الردّ باستخدام validateResponse
  3. قراءة الرد كنص (تلميح: اطّلِع على Response.text())
  4. وعرض النص على الصفحة

يمكنك استخدام الدالة showText التالية كدالة مساعدة لعرض النص النهائي:

function showText(responseAsText) {
  const message = document.getElementById('message');
  message.textContent = responseAsText;
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على استرداد النص. إذا نفّذت fetchText بشكل صحيح، من المفترض أن يظهر لك نص إضافي على الصفحة.

ملاحظة: على الرغم من أنّ جلب HTML وإلحاقه باستخدام السمة innerHTML قد يكون أمرًا مغريًا، عليك توخّي الحذر. قد يؤدي ذلك إلى تعرُّض موقعك الإلكتروني لهجمات اختراق عبر المواقع الإلكترونية.

لمزيد من المعلومات

تستخدِم الدالة fetch تلقائيًا طريقة GET التي تستردّ مصدرًا معيّنًا. ولكن يمكن أن تستخدم الدالة fetch أيضًا طرق HTTP أخرى.

إرسال طلب HEAD

استبدِل الدالة headRequest بالرمز التالي:

function headRequest() {
  fetch('examples/words.txt', {
    method: 'HEAD'
  })
  .then(validateResponse)
  .then(readResponseAsText)
  .then(logResult)
  .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على طلب HEAD. لاحظ أنّ محتوى النص الذي تم تسجيله فارغ.

الشرح

يمكن أن تتلقّى الطريقة fetch مَعلمة ثانية اختيارية، وهي init. تتيح هذه المَعلمة إعداد طلب الجلب، مثل طريقة الطلب ووضع ذاكرة التخزين المؤقت وبيانات الاعتماد وغير ذلك.

في هذا المثال، نضبط طريقة طلب الجلب على HEAD باستخدام المَعلمة init. تشبه طلبات HEAD طلبات GET، باستثناء أنّ نص الردّ يكون فارغًا. يمكن استخدام هذا النوع من الطلبات عندما تريد الحصول على بيانات وصفية عن ملف فقط بدون الحاجة إلى نقل جميع بيانات الملف.

اختياري: البحث عن حجم أحد المراجع

لنلقِ نظرة على العناوين الخاصة باستجابة عملية الجلب لـ examples/words.txt من أجل تحديد حجم الملف.

عدِّل الدالة headRequest لتسجيل السمة content-length الخاصة بالرد headers (ملاحظة: راجِع المستندات المتعلقة بالعناوين وطريقة get).

بعد تعديل الرمز، احفظ الملف وأعِد تحميل الصفحة. انقر على طلب HEAD. يجب أن تسجّل وحدة التحكّم حجم examples/words.txt (بالبايت).

الشرح

في هذا المثال، يتم استخدام طريقة HEAD لطلب حجم مورد (بالبايت) (ممثَّل في العنوان content-length) بدون تحميل المورد نفسه فعليًا. في الواقع، يمكن استخدام ذلك لتحديد ما إذا كان يجب طلب المورد الكامل (أو حتى كيفية طلبه).

اختياري: يمكنك معرفة حجم examples/words.txt باستخدام طريقة أخرى والتأكّد من أنّه يتطابق مع القيمة من عنوان الاستجابة (يمكنك البحث عن كيفية إجراء ذلك لنظام التشغيل المحدّد الذي تستخدمه، وستحصل على نقاط إضافية إذا استخدمت سطر الأوامر).

لمزيد من المعلومات

يمكن أن يرسل Fetch أيضًا بيانات مع طلبات POST.

إعداد خادم echo

في هذا المثال، عليك تشغيل خادم echo. من الدليل fetch-api-lab/app/، نفِّذ الأمر التالي (إذا كان خادم localhost:8081 يحظر سطر الأوامر، افتح نافذة أو علامة تبويب جديدة لسطر الأوامر):

node echo-servers/cors-server.js

يبدأ هذا الأمر تشغيل خادم بسيط على localhost:5000/ يعكس الطلبات المُرسَلة إليه.

يمكنك إيقاف هذا الخادم في أي وقت باستخدام ctrl+c.

إجراء طلب POST

استبدِل الدالة postRequest بالرمز التالي (تأكَّد من تحديد الدالة showText من القسم 4 إذا لم تكمل القسم):

function postRequest() {
  fetch('http://localhost:5000/', {
    method: 'POST',
    body: 'name=david&message=hello'
  })
    .then(validateResponse)
    .then(readResponseAsText)
    .then(showText)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. انقر على طلب POST. لاحظ الطلب المُرسَل الذي تم عرضه على الصفحة. يجب أن يحتوي على الاسم والرسالة (يُرجى العِلم أنّنا لا نحصل على البيانات من النموذج بعد).

الشرح

لإجراء طلب POST باستخدام fetch، نستخدِم المَعلمة init لتحديد الطريقة (على غرار طريقة ضبط طريقة HEAD في القسم السابق). هذا هو المكان الذي نضبط فيه نص الطلب، وهو عبارة عن سلسلة بسيطة في هذه الحالة. النص هو البيانات التي نريد إرسالها.

ملاحظة: في مرحلة الإنتاج، احرص دائمًا على تشفير أي بيانات حساسة للمستخدمين.

عندما يتم إرسال البيانات كطلب POST إلى localhost:5000/، يتم إعادة الطلب كاستجابة. بعد ذلك، يتم التحقّق من صحة الرد باستخدام validateResponse، وقراءته كنص، وعرضه على الصفحة.

في الواقع، سيمثّل هذا الخادم واجهة برمجة تطبيقات تابعة لجهة خارجية.

اختياري: استخدام واجهة FormData

يمكنك استخدام واجهة FormData للحصول على البيانات من النماذج بسهولة.

في الدالة postRequest، أنشئ مثيلاً جديدًا لكائن FormData من عنصر النموذج msg-form:

const formData = new FormData(document.getElementById('msg-form'));

بعد ذلك، استبدِل قيمة المَعلمة body بالمتغيّر formData.

احفظ النص البرمجي وأعِد تحميل الصفحة. املأ النموذج (الحقلان الاسم والرسالة) في الصفحة، ثم انقر على طلب POST. راقِب محتوى النموذج المعروض على الصفحة.

الشرح

يمكن أن تأخذ الدالة الإنشائية FormData عنصر HTML form، وتنشئ كائن FormData. تتم تعبئة هذا العنصر بمفاتيح النموذج وقيمه.

لمزيد من المعلومات

بدء خادم echo غير CORS

أوقِف خادم echo السابق (من خلال الضغط على ctrl+c من سطر الأوامر) وابدأ خادم echo جديدًا من الدليل fetch-lab-api/app/ عن طريق تنفيذ الأمر التالي:

node echo-servers/no-cors-server.js

يُعدّ هذا الأمر خادمًا بسيطًا آخر لعرض الرسائل، ولكن هذه المرة على المنفذ localhost:5001/. ومع ذلك، لم يتم إعداد هذا الخادم لقبول طلبات من مصادر متعددة.

استرداد البيانات من الخادم الجديد

بعد تشغيل الخادم الجديد على localhost:5001/، يمكننا إرسال طلب جلب إليه.

عدِّل الدالة postRequest لجلب البيانات من localhost:5001/ بدلاً من localhost:5000/. بعد تعديل الرمز، احفظ الملف وأعِد تحميل الصفحة، ثم انقر على طلب POST.

من المفترض أن يظهر لك خطأ في وحدة التحكّم يشير إلى أنّه تم حظر الطلب من مصادر متعددة لأنّ عنوان CORS Access-Control-Allow-Origin غير متوفّر.

عدِّل fetch في الدالة postRequest باستخدام الرمز التالي الذي يستخدم الوضع no-cors (كما يقترح سجلّ الأخطاء)، وأزِل طلبات validateResponse وreadResponseAsText (راجِع التوضيح أدناه):

function postRequest() {
  const formData = new FormData(document.getElementById('msg-form'));
  fetch('http://localhost:5001/', {
    method: 'POST',
    body: formData,
    mode: 'no-cors'
  })
    .then(logResult)
    .catch(logError);
}

احفظ النص البرمجي وأعِد تحميل الصفحة. بعد ذلك، املأ نموذج الرسالة وانقر على طلب POST.

راقِب عنصر الاستجابة الذي تم تسجيله في وحدة التحكّم.

الشرح

تتّبع عملية الجلب (وXMLHttpRequest) سياسة المصدر نفسه. وهذا يعني أنّ المتصفّحات تفرض قيودًا على طلبات HTTP الواردة من عدّة مصادر من داخل النصوص البرمجية. يحدث طلب من مصدر خارجي عندما يطلب نطاق (مثل http://foo.com/) موردًا من نطاق منفصل (مثل http://bar.com/).

ملاحظة: غالبًا ما تكون القيود المفروضة على الطلبات من مصادر متعددة موضع التباس. يتم جلب العديد من الموارد، مثل الصور وأوراق الأنماط والنصوص البرمجية، من نطاقات مختلفة (أي من مصادر متعددة). ومع ذلك، هذه استثناءات للسياسة المشتركة المصدر. لا يزال بإمكان النصوص البرمجية حظر الطلبات من مصادر خارجية.

بما أنّ خادم تطبيقنا يستخدم رقم منفذ مختلفًا عن رقمَي منفذَي خادمي الصدى، تُعتبر الطلبات المُرسَلة إلى أيّ من خادمي الصدى طلبات من مصادر متعددة. ومع ذلك، تم ضبط خادم الصدى الأول الذي يعمل على localhost:5000/ على إتاحة CORS (يمكنك فتح echo-servers/cors-server.js وفحص الإعداد). لا يتوفّر خادم الصدى الجديد الذي يعمل على localhost:5001/ (وهذا هو سبب ظهور الخطأ).

يتيح استخدام mode: no-cors جلب ردّ مبهم. يسمح ذلك بالحصول على ردّ، ولكنّه يمنع الوصول إلى الردّ باستخدام JavaScript (وهذا هو السبب في عدم إمكانية استخدام validateResponse أو readResponseAsText أو showResponse). ويمكن استهلاك الردّ من خلال واجهات برمجة تطبيقات أخرى أو تخزينه مؤقتًا بواسطة مشغّل الخدمات.

تعديل عناوين الطلبات

تتيح واجهة برمجة التطبيقات Fetch أيضًا تعديل عناوين الطلبات. أوقِف خادم localhost:5001 (بدون CORS) وأعِد تشغيل خادم localhost:5000 (مع CORS) من القسم 6:

node echo-servers/cors-server.js

استعادة الإصدار السابق من الدالة postRequest التي تجلب البيانات من localhost:5000/:

function postRequest() {
  const formData = new FormData(document.getElementById('msg-form'));
  fetch('http://localhost:5000/', {
    method: 'POST',
    body: formData
  })
    .then(validateResponse)
    .then(readResponseAsText)
    .then(showText)
    .catch(logError);
}

الآن، استخدِم واجهة Header لإنشاء عنصر Headers داخل الدالة postRequest باسم messageHeaders مع ضبط قيمة العنوان Content-Type على application/json.

بعد ذلك، اضبط السمة headers للعنصر init على المتغيّر messageHeaders.

عدِّل السمة body لتصبح عنصر JSON محوَّلاً إلى سلسلة، مثل:

JSON.stringify({ lab: 'fetch', status: 'fun' })

بعد تعديل الرمز، احفظ الملف وأعِد تحميل الصفحة. بعد ذلك، انقر على إرسال الطلب.

لاحظ أنّ الطلب الذي تمّت إعادة صياغته يتضمّن الآن Content-Type بقيمة application/json (بدلاً من multipart/form-data كما كان في السابق).

الآن، أضِف عنوان Content-Length مخصّصًا إلى العنصر messageHeaders وأعطِ الطلب حجمًا عشوائيًا.

بعد تعديل الرمز البرمجي، احفظ الملف وأعِد تحميل الصفحة وانقر على طلب POST. لاحظ أنّ هذا العنوان لا يتم تعديله في الطلب الذي تمّت إعادة إرساله.

الشرح

تتيح واجهة الرأس إنشاء كائنات الرؤوس وتعديلها. يمكن تعديل بعض العناوين، مثل Content-Type، باستخدام عملية الجلب. أما غيرها، مثل Content-Length، فهي محمية ولا يمكن تعديلها (لأسباب أمنية).

ضبط عناوين طلبات مخصّصة

تتيح عملية الجلب ضبط عناوين مخصّصة.

أزِل العنوان Content-Length من العنصر messageHeaders في الدالة postRequest. أضِف العنوان المخصّص X-Custom مع قيمة عشوائية (مثل X-CUSTOM': 'hello world').

احفظ النص البرمجي، وأعِد تحميل الصفحة، ثم انقر على طلب POST.

من المفترض أن يظهر لك أنّ الطلب الذي تمّت إعادة إرساله يتضمّن السمة X-Custom التي أضفتها.

الآن، أضِف عنوان Y-Custom إلى عنصر العناوين. احفظ النص البرمجي وأعِد تحميل الصفحة، ثم انقر على طلب POST.

من المفترض أن يظهر لك خطأ مشابه لهذا في وحدة التحكّم:

Fetch API cannot load http://localhost:5000/. Request header field y-custom is not allowed by Access-Control-Allow-Headers in preflight response.

الشرح

كما هو الحال مع الطلبات الواردة من مصادر متعددة، يجب أن يتيح الخادم الذي يتم طلب المورد منه استخدام العناوين المخصّصة. في هذا المثال، تم ضبط خادم الصدى لقبول العنوان X-Custom ولكن ليس العنوان Y-Custom (يمكنك فتح echo-servers/cors-server.js والبحث عن Access-Control-Allow-Headers لترى ذلك بنفسك). في كل مرة يتم فيها ضبط عنوان مخصّص، يجري المتصفّح عملية فحص مسبق. وهذا يعني أنّ المتصفّح يرسل أولاً طلب OPTIONS إلى الخادم لتحديد طرق HTTP والعناوين المسموح بها من قِبل الخادم. إذا تم إعداد الخادم لقبول طريقة الطلب الأصلي وعناوينه، يتم إرساله، وإلا سيتم عرض خطأ.

لمزيد من المعلومات

رمز الحلّ

للحصول على نسخة من الرمز البرمجي الذي يعمل، انتقِل إلى مجلد الحل.

أنت تعرف الآن كيفية استخدام Fetch API.

الموارد

للاطّلاع على جميع دروس البرمجة في دورة تدريب تطبيقات الويب التقدّمية، راجِع درس البرمجة الترحيبي للدورة التدريبية.