الدليل
الأخطاء
غلاف واحد لكل إخفاق، وعشرة رموز عامة تبني عليها قرارك، ورسالة مترجَمة منفصلة يجب ألا يحلّلها برنامجك ولا يقارنها أبدًا.
كل رد غير ناجح من واجهة X-Radius هو الكائن نفسه. لا شكل خطأ ثانٍ، ولا جسم نصّي
عارٍ، ولا صفحة HTML — حتى في حالة الـ 500.
الغلاف
{
"error": {
"code": "ERR_VALIDATION",
"message": "Request validation failed.",
"request_id": "8f2c1d0a4b",
"details": { "reason": "invalid_expiration" }
}
}
codeصنف، لا حادثة بعينها. وهو ثابت وبأحرف كبيرة وآمن أن تبني عليه قرارك.messageنثر للبشر، مترجَم سلفًا إلى لغة المنادي. وليس عقدًا. عامله على أنه غير مستقر في صياغته ولا في لغته.request_idيحدّد الطلب بعينه في سجل الخادم. اذكره في محادثة الدعم؛ فهو عادةً الفرق بين تشخيص وتخمين.detailsموجود في بعض الإخفاقات فقط. وحين يوجد يحملreason، وهو مميِّز ثابت يقرؤه البرنامج، ويحمل أحيانًا حقلًا أرسله المنادي معادًا كما هو، ليبلّغ البرنامج عما حاول فعله بلا تحليل نثر.
وردود النجاح هي الصورة المقابلة: كائن واحد تحت data، مع كتلة meta تضيفها
نقاط القوائم.
الرموز العامة العشرة
هذه العشرة هي كامل مفردات حقل الصنف. وكل حالة أدناه هي الحالة المتعارف عليها؛ والمعالج يختار الحالة صراحةً، فقد يظهر الرمز مع حالة أخرى حيث يقتضي السياق.
| الرمز | الحالة | المعنى |
|---|---|---|
ERR_VALIDATION |
400 | الطلب مشوَّه، أو قيمة خارج المدى أو غير مسموحة. وهو الأكثر شيوعًا بفارق كبير. |
ERR_UNAUTHORIZED |
401 | بيانات الاعتماد مفقودة أو مشوَّهة أو لم تعد سارية. |
ERR_FORBIDDEN |
403 | بيانات الاعتماد سليمة؛ الصلاحية ليست كذلك. |
ERR_NOT_FOUND |
404 | لا سجل بهذا المعرّف — أو سجل لا يحقّ لك رؤيته. والجوابان متطابقان عن قصد. |
ERR_CONFLICT |
409 | الطلب يناقض الحالة الراهنة: اسم مستخدم مأخوذ، أو كرت استُهلك، أو مفتاح منع تكرار مرتبط بموضوع آخر. |
ERR_RATE_LIMITED |
429 | نفدت ميزانية طلبات. انظر حدود المعدل. |
ERR_INTERNAL |
500 | عطل من جهتنا. وrequest_id هو الشيء الوحيد المفيد الذي ترسله إلينا. |
ERR_TIMEOUT |
503 | لم يتسع العمل لميزانية الطلب أو ميزانية الجملة. لا شيء معطوب؛ أعد المحاولة، ويفضَّل بنطاق أضيق. |
ERR_LICENSE_BLOCKED |
403 | المستأجر تجاوز سقف مشتركيه أو انتهى ترخيصه. وواجهة الإدارة كلها مقفلة على صفحة الترخيص حتى يُحلّ ذلك. |
ERR_MAINTENANCE |
503 | وُضعت النسخة في وضع الصيانة من لوحة المشغّل. وليس حكمًا على طلبك. |
واثنان من هذه يستحقان نظرةً ثانية:
ERR_TIMEOUT هو 503 ويختلف عن ERR_INTERNAL عن قصد. يُطلق حين تنقضي ميزانية
الطلب أو مهلة جملة قاعدة البيانات. لا شيء خاطئ؛ الاستعلام ببساطة أكبر من الوقت
المسموح. فضيّق المرشّح أو الصفحة وأعد المحاولة.
وERR_NOT_FOUND يغطي "غير موجود" و"موجود لكنه خارج شجرة مديرك" معًا. فالـ
403 في تلك المسارات يؤكد وجود السجل ويجعل المعرّفات قابلة للتعداد، فالجوابان
متطابقان حرفًا بحرف، بما في ذلك details.reason.
ويوجد رمز آخر قد يصلك على واجهة المستأجر وليس في ذلك الجدول:
ERR_UNAVAILABLE بحالة 503، مع details.reason تساوي site_offline، حين
يطفئ مشغّل بوابة المستأجر. ويُجاب به عند الدخول وعند مداخل بوابة المشترك فقط.
الرموز مقابل الأسباب
حقل code خشن بحكم التصميم، وعدة نتائج شديدة الاختلاف تتشارك رمزًا واحدًا.
فستة إخفاقات دخول مختلفة كلها تجيب ERR_UNAUTHORIZED: لا حساب بهذا الاسم،
كلمة مرور خاطئة، مطلوب تحقق بخطوتين، تحقق بخطوتين خاطئ، جلسة أُبطلت، رمز
انتهى. والصنف واحد فعلًا، والبرنامج الذي يريد التفريق بينها يحتاج شيئًا أدقّ.
وذلك الشيء هو details.reason. وهو دائمًا مفتاح الرسالة الذي بنى به الخادم
النثر المترجَم، فيبقى الاثنان متوافقين بالبناء. والمفاتيح نحو ألف ومئتين، فلا
تحاول حصرها — بدّل على الحفنة التي يحتاجها تكاملك فعلًا، ودع الباقي يسقط إلى
الرمز.
{
"error": {
"code": "ERR_UNAUTHORIZED",
"message": "Two-factor authentication is required.",
"request_id": "1c7f0b99e2",
"details": { "reason": "mfa_required" }
}
}
وليس كل إخفاق يحمل details. فإخفاقات المصادقة وحدود المعدل ورفض مفاتيح منع
التكرار تحملها. أما رفض الصلاحية البسيط فلا: الـ 403 بالرمز ERR_FORBIDDEN
الصادر عن بوابة الصلاحيات يحمل الرمز والرسالة فقط.
الرسائل مترجَمة، فلا تطابقها أبدًا
يُعرض حقل message بلغة المنادي، تُختار من ترويسة Accept-Language وترتدّ إلى
لغة المستأجر الافتراضية. فالإخفاق نفسه نثرٌ إنجليزي عند عميل ونثرٌ عربي عند
آخر:
curl -s https://acme.example.com/api/v1/users/999999 \
-H "Authorization: Bearer $XRADIUS_TOKEN" \
-H "Accept-Language: ar"
والبرنامج الذي يقارن نص الرسالة يُكسر لحظة يحسّن مترجم جملةً، ويُكسر عند كل
منادٍ لغته ليست اللغة التي كُتب البرنامج عليها. ابنِ قرارك على error.code، ثم
على error.details.reason إن احتجت التفصيل. واعرض message للناس، وسجّل
request_id، وعامل الاثنين بوصفهما بياناتٍ تمرّرها لا منطقًا تعتمد عليه.
معالجة عملية
البرنامج المعقول يفرّق بين أربع حالات ويتجاهل ما عداها:
- أعد المحاولة كما هي —
ERR_TIMEOUTوERR_MAINTENANCE، وERR_INTERNALبعد مهلة. تراجع تدريجيًا، ولا تطرق الباب بعنف. - أعد المحاولة بعد انتظار —
ERR_RATE_LIMITED. لا ترويسةRetry-After، فتراجع وفق جدولك أنت. - أصلح الطلب —
ERR_VALIDATIONوERR_CONFLICT. فإعادة إرسال البايتات نفسها ستفشل بالطريقة نفسها. - أصلح بيانات الاعتماد أو الإعداد —
ERR_UNAUTHORIZEDوERR_FORBIDDENوERR_LICENSE_BLOCKED. لا شيء يفعله برنامجك وقت التشغيل يحلّ هذه.
وERR_NOT_FOUND هو الخامس، وينتمي إلى أيٍّ من هذه الأربع يقرّره نموذج بياناتك.
وإعادة محاولة أي عملية تحرّك مالًا أو تجهّز خدمة يجب أن تعيد استعمال مفتاح منع التكرار الأصلي. انظر منع التكرار؛ فالخطأ هنا هو ما يحوّل انقضاء مهلة إلى خصم مزدوج.
آخر تحديث