يمكنك تقديم طلب من الواجهة الأمامية الخاصة بك إلى واجهة برمجة التطبيقات (API) ويقوم المتصفح بحظره باستخدام:Access to fetch at '...' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. يعد هذا أحد الأخطاء الأكثر شيوعًا والتي يساء فهمها في تطوير الويب. إليك ما يسببه بالفعل وكيفية إصلاحه بشكل صحيح.
📋 Table of Contents
ما هو CORS في الواقع
CORS (مشاركة الموارد عبر الأصل) هي آلية أمان للمتصفح. عندما يكون جافا سكريبت قيد التشغيلhttps://app.example.com يقدم طلبًا إلىhttps://api.other.com، يعتبره المتصفح طلبًا عبر الأصل ويطلب من الخادم السماح به صراحةً عبر رؤوس الاستجابة. إذا لم يرسل الخادمAccess-Control-Allow-Origin الذي يتضمن أصلك، يقوم المتصفح بحظر الاستجابة – حتى لو قام الخادم بمعالجة الطلب بنجاح.
البصيرة الرئيسية:يتم فرض CORS بواسطة المتصفح، ويظل الإصلاح موجودًا على الخادم، وليس في كود الواجهة الأمامية الخاص بك. لا يمكنك إصلاح خطأ CORS عن طريق تغيير استدعاء الجلب وحده.
الإصلاح 1: تكوين الخادم لإرسال الرأس
الحل الصحيح هو جعل واجهة برمجة التطبيقات (API) تستجيب برؤوس CORS الصحيحة. في Express، استخدمcors الوسيطة:
const cors = require('cors');
app.use(cors({
origin: 'https://app.example.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));
تعيينorigin إلى الأصل الدقيق للواجهة الأمامية الخاصة بك. لا تستخدم حرف البدل* في الإنتاج إذا قمت بإرسال بيانات الاعتماد (ملفات تعريف الارتباط أو رؤوس المصادقة) – ترفض المتصفحات مجموعةAccess-Control-Allow-Origin: * معcredentials: true.
الإصلاح 2: التعامل مع طلبات الاختبار المبدئي (OPTIONS)
بالنسبة لأي طلب ليس مجرد GET/POST — على سبيل المثال، الطلب الذي يرسلContent-Type: application/json أوAuthorization الرأس – يرسل المتصفح أولًا اختبارًا مبدئيًاOPTIONS طلب الإذن. يجب أن يستجيب خادمك لها بالرؤوس المناسبة.cors تتعامل البرامج الوسيطة المذكورة أعلاه مع هذا تلقائيًا، ولكن إذا قمت بتعيين الرؤوس يدويًا، فيجب عليك التعامل مع الخيارات بشكل صريح:
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://app.example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
return res.sendStatus(204); // Respond to preflight, do not fall through
}
next();
});
من الأخطاء الشائعة الفشل في الاستجابة للاختبار المبدئي لـ OPTIONS — يرسله المتصفح، ولا يحصل على استجابة CORS صالحة، ويحظر الطلب الحقيقي قبل تقديمه.
الإصلاح 3: تطابق الأصل تمامًا
يجب أن يتطابق الأصل بدقة — يتم احتساب كل من البروتوكول والمجال والمنفذ. هذه كلها أصول مختلفة للمتصفح:
| الأصل | لماذا يختلف |
|---|---|
| http://localhost:3000 | بروتوكول مختلف عن https |
| https://localhost:3000 | بروتوكول مختلف عن http |
| https://example.com | منفذ مختلف من :3000 |
| https://www.example.com | يختلف النطاق الفرعي www عن النطاق الرئيسي |
إذا كان أصلك المسموح به هوhttps://example.com ولكن يتم تحميل تطبيقك منhttps://www.example.com، CORS يحظره. السماح بكل أصل يستخدمه التطبيق فعليًا، أو التطبيع مع مصدر واحد.
الإصلاح 4: استخدام الأصل الديناميكي للواجهات الأمامية المتعددة
إذا كانت عدة أصول بحاجة إلى الوصول (التدريج والإنتاج والمضيف المحلي)، فقم بالتحقق من القائمة المسموح بها بدلاً من قائمة الترميز الثابت:
const allowed = [
'https://app.example.com',
'https://staging.example.com',
'http://localhost:3000'
];
app.use(cors({
origin: (origin, callback) => {
if (!origin || allowed.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true
}));
الإصلاح 5: للتطوير المحلي، استخدم الوكيل
أثناء التطوير، يمكنك تجاوز CORS عن طريق وكيل طلبات API من خلال خادم التطوير الخاص بك بحيث تظهر من نفس الأصل. في فايت:
// vite.config.js
export default {
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true
}
}
}
};
الآن تستدعي الواجهة الأمامية/api/... من أصله الخاص ويقوم خادم التطوير بإعادة توجيهه. يعد هذا بمثابة تسهيل تطوير، وليس إصلاحًا للإنتاج – لا يزال الإنتاج يحتاج إلى رؤوس CORS مناسبة على واجهة برمجة التطبيقات (API).
ما لا يجب فعله
لا تصل إلى ملحقات المتصفح التي تعطل CORS، ولا تصفعAccess-Control-Allow-Origin: * على كل شيء لجعل الخطأ يختفي. يعرض حرف البدل واجهة برمجة التطبيقات (API) الخاصة بك لكل موقع على الإنترنت ويقطع طلبات بيانات الاعتماد. CORS هي إحدى ميزات الأمان — قم بتكوينها بشكل صحيح بدلاً من تعطيلها.
الأسئلة المتداولة
س: لماذا يعمل الطلب في Postman وليس في المتصفح؟
ج: لا يقوم Postman بفرض CORS — فقط المتصفحات هي التي تفعل ذلك. الطلب الذي يصل إلى الخادم يثبت أن الخادم يعمل؛ يقوم المتصفح بحظر الاستجابة لأن رؤوس CORS مفقودة. إصلاح الرؤوس على الخادم.
س: هل يمكنني إصلاح CORS من الواجهة الأمامية؟
ج: لا. يجب أن تأتي رؤوس CORS من الخادم الذي يستجيب للطلب. الحل البديل الوحيد من جانب الواجهة الأمامية هو وكيل التطوير، الذي يجعل الطلبات من نفس المصدر أثناء التطوير.
س: لماذا يفشل طلب OPTIONS الخاص بي في الاختبار المبدئي؟
ج: الخادم لا يستجيب للخيارات ذات رؤوس CORS الصحيحة وحالة 2xx. تأكد من تشغيل برنامج CORS الوسيط قبل مساراتك، أو تعامل مع الخيارات بشكل صريح وقم بإرجاع 204.
س: لماذا تنفصل بيانات الاعتماد: صحيح عن الأصل ‘*’؟
ج: تمنع المتصفحات إرسال بيانات الاعتماد (ملفات تعريف الارتباط، المصادقة) عندما يكون الأصل المسموح به هو حرف البدل*. حدد الأصل الدقيق بدلاً من ذلك عندما تحتاج إلى بيانات الاعتماد.
س: الرأس موجود ولكنه ما زال فاشلاً. لماذا؟
ج: تأكد من أن الأصل يتطابق تمامًا مع (البروتوكول، والمجال، والمنفذ)، وأنه تمت معالجة الاختبار المبدئي لـ OPTIONS، وأن الوكيل أو CDN الموجود في المقدمة لا يقوم بتجريد الرأس. افحص رؤوس الاستجابة الفعلية في علامة التبويب “الشبكة”.
الخلاصة
الخطأ “لا يوجد رأس Access-Control-Allow-Origin موجود” يعني أن المتصفح قام بحظر الاستجابة عبر الأصل لأنالخادم لم يسمح بأصلك. الإصلاح موجود دائمًا على الخادم:أرسل الصحيحAccess-Control-Allow-Origin header، والتعامل مع الاختبار المبدئي OPTIONS، ومطابقة الأصل تمامًا، وعدم استخدام حرف بدل مع بيانات الاعتماد. بالنسبة للتطوير المحلي، يتجنب وكيل التطوير المشكلة بشكل واضح. بمجرد أن يقوم الخادم بإرجاع الرؤوس الصحيحة لأصلك الدقيق ويستجيب لطلبات الاختبار المبدئي، يختفي الخطأ ويتم تنفيذ طلباتك.
🔗 Share this article
✍️ Leave a Comment