ما هو خطأ CORS؟
CORS = Cross-Origin Resource Sharing. هي سياسة أمان في المتصفّح تمنع موقعاً من طلب بيانات من موقع آخر بدون إذن.
مثال: موقعك على localhost:3000 يحاول طلب API على localhost:5000. المتصفّح يرى أنهما "origin" مختلفان (المنفذ مختلف) فيرفض الطلب.
الخطأ الذي تراه:
Access to fetch at 'http://localhost:5000/api/users' from origin
'http://localhost:3000' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested resource.لماذا لا نتجاهله فقط؟
CORS موجود لحمايتك. بدون CORS، موقع ضارّ يستطيع إرسال طلبات باسم المستخدم لأي API هو مسجّل دخوله إليه — سرقة بيانات، تحويلات مالية، إلخ.
الحلّ ليس "إغلاق" الأمان، بل إخبار الخادم أن يسمح لمصدرك تحديداً.
الحل الصحيح: حزمة cors
تثبيتها في مشروع Express:
npm install corsالاستخدام الأبسط (تطوير فقط)
import express from "express";
import cors from "cors";
const app = express();
// يسمح لأيّ origin — مناسب للتطوير
app.use(cors());
app.get("/api/users", (req, res) => {
res.json([{ id: 1, name: "أحمد" }]);
});
app.listen(5000);⚠️ لا تستخدم هذا في الإنتاج — أيّ موقع يستطيع طلب API الخاص بك.
الإعداد الآمن للإنتاج
حدّد المصادر المسموح لها بالضبط:
const allowedOrigins = [
"http://localhost:3000",
"https://khubarae.com",
"https://www.khubarae.com",
];
app.use(cors({
origin: (origin, callback) => {
// السماح للطلبات بدون origin (Postman, mobile apps, cURL)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error("المصدر غير مسموح به"));
}
},
credentials: true, // إن كنت ترسل cookies
}));أشكال مختلفة من CORS
طلب بسيط (Simple Request)
GET/POST/HEAD بدون headers مخصّصة. المتصفّح يرسله مباشرة ويتحقّق من headers الرد.
طلب Preflight
يحدث تلقائياً حين:
- الـ method ليس GET/POST/HEAD
- ترسل
Content-Type: application/json - ترسل headers مخصّصة (مثل
Authorization)
المتصفّح يرسل OPTIONS أولاً، ينتظر موافقة الخادم، ثم يرسل الطلب الفعلي. حزمة cors تتعامل مع هذا تلقائياً.
Credentials (Cookies والتوكينات)
إن كان API يستخدم cookies (جلسات)، تحتاج إعدادين:
على الخادم:
app.use(cors({
origin: "http://localhost:3000",
credentials: true,
}));على العميل:
fetch("http://localhost:5000/api/me", {
credentials: "include", // أرسل الكوكيز
});⚠️ تحذير: عندما credentials: true، لا يمكن تعيين origin: "*". يجب تحديد مصدر دقيق.
الأخطاء الشائعة وحلولها
1. "Credentials flag is true, but Access-Control-Allow-Origin is *"
السبب: لا يمكن استخدام * مع الكوكيز.
الحل: حدّد الـ origin بالضبط:
// ❌
app.use(cors({ origin: "*", credentials: true }));
// ✅
app.use(cors({ origin: "http://localhost:3000", credentials: true }));2. "Method not allowed"
app.use(cors({
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"],
}));3. Headers غير مقبولة
app.use(cors({
allowedHeaders: ["Content-Type", "Authorization", "X-Custom-Header"],
}));4. CORS لا يعمل رغم إضافته
- تأكّد أن
cors()قبل تعريف الـ routes - إعادة تشغيل السيرفر بعد التعديل
- امسح cache المتصفّح
CORS لكل route على حدة
const corsStrict = cors({ origin: "https://trusted.com" });
const corsPublic = cors({ origin: "*" });
app.get("/api/public", corsPublic, handler);
app.get("/api/private", corsStrict, handler);ما لا يحلّه CORS
CORS ليس بديلاً عن:
- Authentication — تحقّق من هوية المستخدم
- Rate limiting — منع الإفراط في الطلبات
- Input validation — تنقية البيانات الواردة
CORS فقط يحدّد من يستطيع الاستدعاء، ليس ماذا يستطيع فعله.
الأسئلة الشائعة
CORS خطأ في الـ frontend أم الـ backend؟
في الـ backend. المتصفّح يشتكي، لكن الحلّ في headers الخادم. لا يمكن إصلاحه من JavaScript في الواجهة.
هل أستخدم cors في Next.js API Routes؟
Next.js يتعامل تلقائياً مع CORS للطلبات من نفس النطاق. لـ API خارجي، أضف headers يدوياً:
export async function GET() {
return new Response(JSON.stringify({ ok: true }), {
headers: {
"Access-Control-Allow-Origin": "https://trusted.com",
"Content-Type": "application/json",
},
});
}Proxy حلّ بديل؟
نعم — يمكن إعداد Next.js next.config.js لإعادة توجيه /api/* إلى الخادم الخلفي، فيبدو للمتصفّح أنه نفس المصدر. مفيد في التطوير.
مقالات ذات صلة
بناء REST API كامل بـ Node.js و Express: مشروع عملي
اصنع REST API جاهز للإنتاج بـ Node.js — CRUD كامل، معالجة أخطاء، التحقّق من البيانات، وربط PostgreSQL.
الفرق بين SSR و SSG و ISR: متى تستخدم كل واحد؟
ثلاث استراتيجيات للعرض في Next.js — أيّها الأنسب لموقعك؟ شرح عملي بأمثلة وحالات استخدام حقيقية.
React Hooks: شرح useState و useEffect بأمثلة عملية
دليل عملي لأهم hooks في React: useState لإدارة الحالة و useEffect للتعامل مع الآثار الجانبية. أمثلة كاملة بدون حشو.