حل مشكلة CORS في Express: الدليل العملي الكامل
تطوير الويب

حل مشكلة CORS في Express: الدليل العملي الكامل

واجهت خطأ CORS في تطبيق Node.js؟ تعلّم ما هو، لماذا يحدث، وكيف تُصلحه بطريقة صحيحة (ليس بفتح كل شيء).

م
مؤسس LahbabiGuide
3 دقائق قراءة
شارك:

ما هو خطأ 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:

bash
npm install cors

الاستخدام الأبسط (تطوير فقط)

js
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 الخاص بك.

إعلان

الإعداد الآمن للإنتاج

حدّد المصادر المسموح لها بالضبط:

js
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 (جلسات)، تحتاج إعدادين:

على الخادم:

js
app.use(cors({
  origin: "http://localhost:3000",
  credentials: true,
}));

على العميل:

js
fetch("http://localhost:5000/api/me", {
  credentials: "include", // أرسل الكوكيز
});

⚠️ تحذير: عندما credentials: true، لا يمكن تعيين origin: "*". يجب تحديد مصدر دقيق.

الأخطاء الشائعة وحلولها

1. "Credentials flag is true, but Access-Control-Allow-Origin is *"

السبب: لا يمكن استخدام * مع الكوكيز.

الحل: حدّد الـ origin بالضبط:

js
// ❌
app.use(cors({ origin: "*", credentials: true }));

// ✅
app.use(cors({ origin: "http://localhost:3000", credentials: true }));

2. "Method not allowed"

js
app.use(cors({
  methods: ["GET", "POST", "PUT", "DELETE", "PATCH"],
}));

3. Headers غير مقبولة

js
app.use(cors({
  allowedHeaders: ["Content-Type", "Authorization", "X-Custom-Header"],
}));

4. CORS لا يعمل رغم إضافته

  • تأكّد أن cors() قبل تعريف الـ routes
  • إعادة تشغيل السيرفر بعد التعديل
  • امسح cache المتصفّح

CORS لكل route على حدة

js
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 يدوياً:

js
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/* إلى الخادم الخلفي، فيبدو للمتصفّح أنه نفس المصدر. مفيد في التطوير.

شارك:
المزيد من تطوير الويب
اقرأ أيضاً

مقالات ذات صلة