CORS والأصول المسموح بها
يمكن أن يتضمن المفتاح القابل للنشر قائمةً بـ الأصول المسموح بها، وهي مواقع الويب التي يُسمح لها باستخدامه. تشرح هذه الصفحة مواضع التحقق من القائمة، وما يعرضه المتصفح عند فشل التحقق، وما الذي لا توفر القائمة حمايةً له.
يتكوّن الأصل من المخطط والمضيف والمنفذ الخاص بالصفحة، مثل https://www.example.com أو http://localhost:3000. ولا يتضمن مسارًا.
القائمة اختيارية
يعمل المفتاح القابل للنشر حتى إذا كان ت القائمة فارغة. تعني القائمة الفارغة أنه يمكن لأي أصل استخدام المفتاح. وهذه هي حالة المفتاح الذي يُنشأ من دون تحديد أصول، ويمكنك أيضًا إفراغ القائمة لاحقًا.
أضف الأصول قبل وضع المفتاح على موقع إنتاجي. عند إعداد القائمة، لن تعمل نسخة من مفتاحك إذا لُصقت في صفحة ويب خاصة بشخص آخر. وتوضح الفقرة أدناه ما الذي توفره هذه الحماية وما حدودها.
تتجاهل مفاتيح الخادم هذه القائمة. ولا يمكن استخدام مفتاح خادم من داخل المتصفح، مهما كانت الأصول المدرجة في قائمته.
كيفية كتابة إدخال
| القاعدة | المثال |
|---|---|
| اكتب المخطط والمضيف والمنفذ الاختياري فقط. لا تُضف مسارًا أو استعلامًا أو شرطة مائلة في النهاية. | https://www.example.com وليس https://www.example.com/ |
يُشترط استخدام https. ولا يُقبل http إلا مع localhost و127.0.0.1 و[::1]. لا تقبل صفحة مفاتيح API القيمة [::1]؛ اضبطها عبر واجهة API لإدارة المفاتيح. | http://localhost:3000 |
يجب أن تكون المطابقة تامة. لا توجد أحرف بدل، و يُعدّ النطاق الفرعي أصلًا منفصلًا. يُحفظ الإدخال الذي يحتوي على * كما كُتب، لكنه لا يطابق أي موقع. | https://example.com وhttps://www.example.com إدخالان مختلفان |
يُعدّ المنفذ جزءًا من الأصل. احذف المنفذ الافتراضي (443 لـ https و80 لـ http). | https://example.com وليس https://example.com:443 |
| الحد الأقصى 100 إدخال لكل مفتاح. تُرفض الإدخالات المكررة. |
تُخزَّن الإدخالات بأحرف صغيرة مع إزالة المنافذ الافتراضية، لكي تطابق ما يرسله المتصفح.
لا تملك الصفحة المفتوحة مباشرةً من القرص (file://) أصلًا يمكن إضافته. أثناء التطوير، قدّم الصفحة من http://localhost.
اضبط القائمة من صفحة مفاتيح API على kaleidr.com/api-keys، أو باستخدام allowed_origins في واجهة API لإدارة المفاتيح.
مواضع التحقق من القائمة
| الخطوة | الفحص | عند الفشل |
|---|---|---|
| 1. تبادل الجلسة | يجب أن تكون قيمة الترويسة Origin في الطلب موجودة في قائمة المفتاح، إذا كانت له قائمة. | 403 origin_not_allowed. لا تصدر جلسة. أما الطلب الذي لا يتضمن الترويسة Origin أصلًا فيُرجع 403 origin_required. |
| 2. كل استدعاء أثناء التشغيل | لا يعمل رمز الجلسة إلا من الأصل الذي صدر له. | 403 session_origin_mismatch. |
| 3. كل استدعاء أثناء التشغيل | يجب أن يبقى أصل الجلسة ضمن قائمة المفتاح. | 401. تؤدي إزالة أصل من المفتاح إلى إنهاء الجلسات التي سبق إصدارها له. |
| 4. طلبات الخريطة الأساسية المصحوبة بمفتاح | يرسل المحرر المضمَّن مفتاحك القابل للنشر مع طلباته إلى https://tile.kaleidr.com للحصول على النمط والصور الرمزية والخطوط. ويجب أن يكون موقع الصفحة ضمن قائمة المفتاح حتى يُتعرف على المفتاح. | يُعامل الطلب على أنه بلا مفتاح، وقد يُرفض برمز 429 tile_access_restricted. |
| 5. الاستجابة | لا تضيف واجهة API الترويسة Access-Control-Allow-Origin إلا عندما تكون بيانات الاعتماد صالحة والأصل مسموحًا به. | يمنع المتصفح الصفحة من قراءة الاستجابة. |
الخطوة الخامسة هي سلوك CORS المعتاد، وهي سبب ظهور حالات الفشل بهذه الصورة في المتصفح.
الطلب التمهيدي (Preflight)
قبل إرسال طلب POST عبر المواقع يتضمن متن JSON، يرسل المتصفح طلبًا تمهيديًا من نوع OPTIONS. تستجيب Kaleidr لكل طلب تمهيدي بالرمز 204 مع إرجاع الأصل الطالب، لأن الطلب التمهيدي لا يتضمن بيانات اعتماد ولا يمكن التحقق منه باستخدام المفتاح. وتُطبَّق القائمة على الطلب الفعلي.
| ترويسة الاستجابة التمهيدية | القيمة |
|---|---|
Access-Control-Allow-Methods | GET, POST, OPTIONS |
Access-Control-Allow-Headers | Authorization, Content-Type, Accept, X-Api-Key, X-Request-Id |
Access-Control-Max-Age | 600 |
يفشل أي طلب يرسل ترويسة أخرى في مرحلة الطلب التمهيدي داخل المتصفح. لا تضف ترويسات مخصصة إلى الاستدعاءات الصادرة من صفحة ويب.
ترسل واجهة API أيضًا الترويسة Access-Control-Expose-Headers: Retry-After, X-Request-Id في الاستجابات المسموح بها، حتى تتمكن شيفرة الصفحة من قراءة هاتين الترويستين. ولا ترسل Access-Control-Allow-Credentials مطلقًا لأن واجهة API لا تستخدم ملفات تعريف الارتباط.
ما يظهر عند رفض أحد الأصول
عند رفض الأصل أو بيانات الاعتماد، لا تتضمن الاستجابة الترويسة Access-Control-Allow-Origin. ومن ثم يخفي المتصفح الاستجابة عن شيفرتك. لذلك لا ترى الصفحة متن استجابة 401 أو 403، بل يظهر لها خطأ في الشبكة.
في وحدة التحكم:
Access to fetch at 'https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions' from origin
'https://www.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
ثم يظهر خطأ من SDK يحتوي على [kaleidr:chat] (أو اسم المنتج الذي ثبّتَّه). ولا يُعرض أي محتوى.
لمعرفة السبب الحقيقي، افتح علامة التبويب Network في المتصفح، وحدد طلب sessions، ثم اقرأ حالته واستجابته:
| الحالة والرمز في علامة التبويب Network | السبب | الحل |
|---|---|---|
403 origin_not_allowed | أصل هذه الصفحة غير موجود في قائمة المفتاح. | أضف الأصل المطابق تمامًا لما يظهر في ترويسة Origin للطلب. |
401 Invalid or missing API key | المفتاح مكتوب خطأً، أو أُلغي، أو انتهت صلاحيته. | تحقق من المفتاح في صفحة مفاتيح API. |
403 server_key_in_browser | أُرسل مفتاح خادم من صفحة ويب. | استخدم مفتاحًا قابلًا للنشر في الصفحة، ودوّر مفتاح الخادم. |
403 session_origin_mismatch | استُخدم رمز الجلسة من أصل غير الأصل الذي طلب الجلسة. | أجرِ تبادل الجلسة على الصفحة التي تستخدمها. |
فشل الطلب التمهيدي ولا يظهر POST | أرسل الطلب ترويسة غير مدرجة في القائمة المسموح بها. | احذف الترويسة المخصصة. |
بعد قبول بيانات الاعتماد والأصل، تصبح الأخطاء اللاحقة قابلة للقراءة من الصفحة ولا ينتج عنها خطأ CORS. إذا كان المفتاح صالحًا لهذا الأصل لكنه غير مسموح له بهذا المنتج، يفشل تبادل الجلسة باستجابة 403 قابلة للقراءة (product_not_allowed أو insufficient_scope أو tier_capability_not_allowed)، ويسجل SDK الرسالة kaleidr session exchange failed (403). أما استجابة 429 لجلسة صالحة فتصل بمتنها وترويسة Retry-After. تُشرح هذه الرموز في المصادقة والنطاقات.
لا يُظهر الطلب نفسه خطأ CORS عند إرساله من الطرفية، لأن CORS قاعدة تطبقها المتصفحات. لذا يتيح curl التحقق بسرعة من توافق المفتاح والأصل:
curl -i https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions \
-H "X-Api-Key: kld_pk_live_…" \
-H "Origin: https://www.example.com" \
-H "Content-Type: application/json" \
-d '{"product":"chat"}'
يرجع الأصل المسموح به 200 مع access-control-allow-origin: https://www.example.com. أما الأصل المرفوض فيرجع 403 {"detail":"origin_not_allowed"} من دون هذه الترويسة.