يرسل المتصفح أحياناً OPTIONS قبل الطلب الفعلي ليتأكد أن الخادم يسمح بالطريقة والرؤوس المطلوبة من origin مختلف. يضيف هذا الطلب زمناً ومسار استجابة آخر يمكن أن يتأثر بتخزين preflight مؤقتاً. مشروع تخرج هندسة البرمجيات يبني مختبراً بين صفحتين محليتين وخادم API يملكه الفريق، ويعرض الطلب والرد ونتيجة Fetch. لا يستخدم مواقع عامة ولا يختبر تجاوز قيود المتصفح. يصلح هذا النطاق لمشاريع تخرج هندسة البرمجيات التي تشرح تفاعل المتصفح مع واجهة API محلية.
متى يظهر preflight؟
يعتمد القرار على خصائص الطلب، مثل الطريقة والرؤوس وبعض أنواع المحتوى. ينفذ المتصفح preflight للتأكد من أن الخادم يقبل الطلب الفعلي ضمن CORS. يصف معيار WHATWG Fetch خوارزميات CORS وذاكرة preflight في المتصفح؛ ليست كل عملية Fetch تحتاج OPTIONS. ابن مصفوفة طلبات متعمدة بدلاً من القول إن كل cross-origin request يسبقها طلب OPTIONS.
ضع تطبيق الواجهة على origin محلي مثل app.test وAPI على api.test، مع أسماء ثابتة في ملف hosts أو harness يملكه الفريق. أنشئ route واحداً يعيد بيانات اصطناعية. لا تستهدف خدمة جامعية حقيقية حتى لو كان endpoint متاحاً؛ الغرض إظهار استجابة خادم الاختبار وكيف يقرر المتصفح السماح أو المنع. لا تستخدم بيانات اعتماد ولا تعتمد على curl وحده لأن curl لا يطبق سياسة قراءة استجابة CORS مثل المتصفح.
ما الذي يتبادله الطرفان؟
يحمل preflight Origin وAccess-Control-Request-Method وAccess-Control-Request-Headers. يرد الخادم بـAccess-Control-Allow-Origin والطريقة والرؤوس التي يسمح بها، وقد يضيف Access-Control-Max-Age. يشرح دليل MDN لـCORS أن المتصفح لا يرسل الطلب الفعلي في بعض الحالات حتى ينجح الفحص. سجل الرؤوس الفعلية من DevTools ولا تعتمد على نص خطأ ملتبس فقط.
اجعل قائمة السماح صريحة في إعداد المختبر: originين معروفين وطريقتين ورأسين مخصصين. إذا أعاد الخادم السماح لنفس origin، فاختبر تنويع Origin في cache العادي عبر Vary حيث يلزم؛ هذه مسألة response caching تختلف عن CORS-preflight cache الخاصة بالمتصفح. لا تعكس أي Origin يرسله العميل تلقائياً، ولا تجعل wildcard مع credentials خياراً عاماً.
مثال طلب POST ورأس مخصص
ترسل الصفحة المحلية طلب POST مع Content-Type: application/json وX-Lab-Token ذي قيمة تجريبية غير سرية. يسأل المتصفح أولاً إن كانت الطريقة والرؤوس مسموحة. إذا لم يذكر الخادم X-Lab-Token، يرفض المتصفح متابعة الطلب وفق السياسة. بعد تعديل fixture المسموح، يعود preflight ناجحاً ثم يرسل POST. القيم تمثيلية؛ لا تستخدم header يحمل سراً ولا تنقل معلومات حساب إلى origin غير موثوق.
اعرض مرحلة OPTIONS منفصلة عن POST وبيّن أن نجاح preflight لا يعني نجاح العملية نفسها؛ قد يرد الخادم الفعلي 401 أو 500. وبالعكس، قد ينجح الخادم في تنفيذ العملية لكن المتصفح يمنع JavaScript من قراءة الرد بسبب headers. الفرق بين أثر الطلب وحق الصفحة في قراءة الاستجابة نقطة أساسية في التقرير. لا تصف CORS بأنه مصادقة أو جدار يمنع كل حركة من الخادم.
اختبر ذاكرة preflight بحذر
يرشد Access-Control-Max-Age المتصفح إلى مدة تخزين نتيجة الفحص، ويحدد مرجع MDN أن المتصفحات قد تفرض حدوداً داخلية أقصر من الرقم المرسل. ويشرح Fetch أن cache له مفاتيح تشمل origin والرابط والطريقة والرؤوس وغيرها، ويمكن للمتصفح حذف مدخل مبكراً. لذلك لا تتوقع إعادة استخدام واحدة مطابقة لخادم proxy أو CDN.
قارن قيمة max-age قصيرة مثل 5 ثوانٍ مع 60 ثانية في متصفح اختبار، مع إزالة cache أو استخدام profile نظيف بين الحالات. كرر نفس الطلب ثم بدل origin أو اسم الرأس وشاهد هل ظهر OPTIONS ثانية. لا تفترض أن تغيير ACAO في الخادم يبطل الإدخال فوراً في المتصفح؛ سجل الحالة وإصدار المتصفح والوقت. اختبر أيضاً cache العادي منفصلاً، كي لا تنسب استجابة مخزنة لمفتاح HTTP إلى آلية preflight.
افصل credentials عن السماح العام
لا حاجة إلى إرسال cookies في النموذج الأولي. إذا درست credentials في مرحلة لاحقة، احتج إلى origin محدد وقواعد متسقة بين Access-Control-Allow-Credentials وAccess-Control-Allow-Origin. توضح المواصفة أن preflight نفسه لا يحمل credentials مثل الطلب الفعلي، وهذه نقطة يمكن أن تربك المطور عند قراءة سجلات الشبكة. تجنب إظهار cookies أو authorization tokens في لوحة المختبر أو تسجيلها كاملة.
المسموح في CORS لا يعني أن المستخدم مصرح له؛ التفويض يبقى في الخادم. لا تضف قاعدة wildcard وتتعامل معها كطريقة لتجاوز error. مختبرك ينبغي أن يعطي نتيجة «المتصفح لا يسمح للصفحة بقراءة الرد» مع سبب الرؤوس، بينما يحفظ الخادم قرار الدخول منفصلاً. هذا الفصل يقلل فرص تحويل درس البروتوكول إلى إعداد ضعيف.
جدول قبول قابل للإعادة
اختبر origin مسموحاً وآخر غير مدرج، POST ورؤوساً مطلوبة، رأساً غير مسموح، preflight مخزوناً ثم منتهياً، واستجابة OPTIONS مفقودة أو بحالة غير مقبولة. يقبل المختبر إذا شرح الفرق بين الفشل في preflight وبين فشل الاستجابة الفعلية، وسجل هل رأى المتصفح طلباً مسبقاً. أعد التشغيل في profile نظيف لتجنب cache متراكم من جلسة سابقة.
قارن بين توقع مكتوب قبل التشغيل وبين Network panel؛ لا تستنتج أن كل browser build سيخزن للمدة نفسها. لا تستخدم أداة الخادم وحدها لإعلان أن CORS صحيح، لأن المتصفح هو الذي يطبق منع القراءة. نتيجة هذا المشروع هي جدول سلوك محلي محدد، وليست موافقة أمنية على API أو إعداد production.
نطاق مشروع التخرج
يسلم الفريق خادماً محلياً، originين اصطناعيين، مجموعة طلبات ثابتة، صوراً من سجلات DevTools بعد تنقيحها، ومصفوفة headers. تصلح الفكرة ضمن مشاريع التخرج وخدمة تطوير الويب. لا تستعمل مواقع أو حسابات غير مملوكة للفريق ولا تشارك رؤوساً قد تحتوي بيانات مصادقة.
يركز مختبر تقارير CSP على سياسة تحميل الموارد داخل الصفحة، بينما يراجع هذا المشروع إذن قراءة استجابة cross-origin من منظور Fetch. أما مصفوفة cookies فتدرس إرسال ملف الارتباط وخصائصه؛ لا تجعل نجاح CORS بديلاً عن ضبطها. اقرأ القسم الخاص بـpreflight في المواصفة ومراجع MDN قبل توسيع السيناريو إلى أي تطبيق قائم.
المصادر
- WHATWG Fetch Standard: CORS protocol and preflight cache
- MDN: Cross-Origin Resource Sharing (CORS)
- MDN: Access-Control-Max-Age header
مراجعة المصادر: .
اختبار المثال وحدوده
الأصول والنطاقات والرؤوس في السيناريوهات محلية واصطناعية؛ لا توجد طلبات إلى مواقع خارجية أو استنتاجات عن إعدادات خدمة حقيقية.
مقالات ذات صلة
الخدمة المرتبطة: تطوير المواقع والتطبيقات والأنظمة المخصصة.
أرسل متطلبات مشروعك