الخلاصة

  • يعني 429 أن سلسلة طلبات نسبها الخادم إلى موضوع واحد تجاوزت ميزانية محلية؛ ولا يعني أن صياغة الطلب فاسدة، ولا يثبت أن شخصاً بعينه أساء الاستخدام.
  • يمكن أن يحمل الرد Retry-After، لكنه إرشاد زمني لا حجزاً للسعة. تبقى المحاولة اللاحقة خاضعة للحمل والصلاحية والسياسة وحالة المورد في لحظتها.
  • لم يحدد RFC 6585 طريقة تعريف المستخدم أو عد الطلبات. وحّد الحكم الظاهر وترك دفتر الحساب عند المشغّل، ولذلك يجب تدقيق الهوية والنطاق وكلفة الخطأ بدلاً من افتراض عدالة الرمز.

الطلب الحادي والخمسون لم يتغير

لنفرض أن خدمة تقبل خمسين استدعاء في الساعة لكل حساب مسجل. قد يحمل الاستدعاء التالي البنية الصحيحة نفسها، والوجهة نفسها، وبيانات الاعتماد الصالحة نفسها. سبب رفضه لا يسكن بالضرورة في الرسالة، بل في ذاكرة خلفها: جمعه الخادم مع ما سبقه، فوصل المجموع إلى حد اختاره المشغّل.

قبل وجود جواب مخصوص، كان من الممكن إرجاع خطأ عميل عام يوحي بضرورة إصلاح محتوى سليم، أو 503 يوحي بأن الخدمة كلها غير قادرة على العمل بينما تستمر حسابات أخرى. في أبريل 2012 أعطى RFC 6585 هذه الحالة اسماً مشتركاً هو 429 Too Many Requests.

يوصي RFC بأن يشرح تمثيل الرد الحالة، ويجيز Retry-After. ثم يضع الحد الأهم: لا يحدد كيف يتعرف خادم الأصل إلى المستخدم، ولا كيف يعد الطلبات. ما صار مشتركاً هو عبارة الرفض، لا السياسة الحسابية التي أنتجتها.

«المستخدم» مفتاح تجميع لا هوية إنسانية

كي يقرر النظام مبكراً يحتاج إلى علامة تجمع الطلبات. قد تكون حساباً موثقاً، أو مفتاح API، أو cookie للجلسة، أو مستأجراً، أو عنوان مصدر، أو مزيجاً منها. ذكر RFC بيانات الاعتماد وcookie كأمثلة، لا كشهادة بأن كل قيمة تمثل إنساناً واحداً.

عنوان IP رخيص الرؤية عند الحافة، لكنه قد يجمع كثيرين. خلف CGNAT أو مخرج مؤسسة أو وسيط يحمي الخصوصية، يظهر أشخاص غير مرتبطين بعنوان واحد. اندفاع طرف واحد يستهلك رصيد الجميع. عندها يمكن أن يكون 429 صحيحاً بالنسبة إلى عداد العنوان، من دون أن يثبت أن كل فرد مرفوض استنفد حصة شخصية.

الحساب الموثق أقرب أحياناً إلى العقد التجاري، لكنه قد يخدم أجهزة وعمليات وفريقاً كاملاً. وقد يُشارك المفتاح أو يُسرق. أما cookie فيثبت استمرارية جلسة، لا الهوية المدنية. لكل دليل مدى لا يجوز تجاوزه.

يستطيع الخادم القول إن «هذه المجموعة الحسابية بلغت الحد». لا يستطيع أن يجعل الرمز حكماً أخلاقياً على شخص لم تثبته آلية العد.

الرقم نفسه يخفي مجالات مختلفة

يذكر RFC 6585 إمكان العد لكل مورد، أو عبر خادم كامل، أو بين مجموعة خوادم. يحمي الحد الخاص بمورد بحثاً مكلفاً ويترك الإعدادات العادية مفتوحة. أما حد الخادم كله فيحمي سعة مشتركة، لكنه قد يساوي بين قراءة خفيفة وعمل تحليلي ثقيل.

حد المستأجر قد يطابق توزيعاً تعاقدياً إذا نُسب كل طلب إلى مستأجره الصحيح. والعداد المشترك بين المناطق يحافظ على رصيد واحد، لكنه يفرض قرارات عند تأخر النسخ أو انقسام الشبكة أو تعطل مخزن الحالة.

حتى لحظة استهلاك الوحدة تحتاج إلى تعريف. هل تُحسب عند الوصول، أم بعد التوثيق، أم عند القبول، أم بعد انتهاء العمل؟ هل يستهلك التحويل وحدة جديدة؟ هل يبقى تدفق HTTP/2 الملغى في الحساب؟ ومن يدفع إعادة محاولة نفذها وسيط؟ لا يجيب البروتوكول لأن النظام الذي يملك التنفيذ هو من يملك هذه الوقائع.

قد يصدر 429 صحيح البنية من عداد خاطئ. صحة الرسالة ليست مراجعة لصحة الحساب.

وقت العودة ليس موعداً مضموناً

يعرّف RFC 9110 Retry-After كتاريخ HTTP أو عدداً صحيحاً غير سالب من الثواني بعد استلام الرد. ويجيز RFC 6585 إرفاقه بـ429 من دون إلزام.

يخبر الشكلان العميل بألا يعود قبل وقت مناسب، ولا يمنحانه مقعداً في طابور المستقبل. يحتاج التاريخ إلى مرجع زمني صالح، بينما يبدأ التأخير من الاستلام. وكلاهما قد يوقظ آلاف العملاء عند الحد نفسه، فيحوّل التعافي إلى موجة جديدة.

عند العودة يمكن أن تكون السعة قد استُهلكت، أو السياسة قد تغيرت، أو الاعتماد قد انتهى، أو المورد قد تبدل. لذلك يحتاج العميل إلى انضباط محلي: عدد محاولات محدود، وتوزيع أوقات الاستيقاظ، وموعد تنتهي عنده فائدة العمل، وفحص معنى الطريقة قبل التكرار.

لا تصبح العملية غير التكرارية آمنة لأن الساعة تحركت. وإذا وقع غموض في النقل، فلا يثبت المؤقت ما إذا كانت محاولة سابقة قد أحدثت أثراً.

429 و503 يضعان السبب في مكانين

يصف RFC 9110 الرمز 503 بأنه عجز مؤقت لدى الخادم بسبب حمل زائد أو صيانة. أما 429 فيصف كثرة الطلبات بحسب الموضوع والنافذة اللذين اختارتهما سياسة المعدل. قد يحمل كلاهما Retry-After، لكن الحقل المشترك لا يمحو اختلاف المسؤولية.

يمكن أن يتلقى مستأجر واحد 429 وتبقى الخدمة مفتوحة للآخرين. ويمكن أن تتلقى الحسابات كلها 503 من دون أن تتجاوز واحدة منها حصتها. وحين تجتمع الحمايتان، ينبغي أن يسمي الرد الشرط الذي اتخذ قرار الرفض فعلاً.

تصوير نقص السعة العام كخطأ عميل ينقل اللوم. وتصوير حد محلي كتعطل شامل يخفي المسارات الباقية. دقة الحالة يجب أن تكشف سطح التحكم لا أن تجمله.

قول «لا» يستهلك مورداً أيضاً

تحذر اعتبارات الأمن في RFC 6585 من أن الرد بـ429 على كل طلب أثناء هجوم أو سيل كبير من طرف واحد يستهلك الموارد. لذلك لا يُلزم الخادم باستخدام الرمز دائماً؛ قد يكون إسقاط الاتصال أو إجراء آخر أنسب.

قبل رفض مهذب قد يكون الخادم فك التشفير، وحلل الرسالة، ووثق الهوية، واستشار عداداً موزعاً، وأنشأ النص، ثم شفر الرد وأرسله. إذا فرض دخل رخيص هذه السلسلة كاملة، صارت الشفافية كلفة يشتريها المهاجم.

الرفض المبكر عند الحافة أوفر، لكنه يرى عادة دليلاً أضعف، كعنوان مشترك. ينخفض العمل وتزداد إصابة الأبرياء. لذلك يجب أن يظل الإجراء المبكر ضيقاً وقابلاً للعكس بقدر ضعف الهوية المتاحة.

لماذا لا يجوز للذاكرة المخبأة تمديد الرفض

يحظر RFC 6585 تخزين رد 429 في cache. القرار مرتبط بموضوع ووقت ونطاق وعدّ حالي. إعادة استعماله قد تمد نافذة انتهت أو تنقل دين موضوع إلى سياق طلب آخر.

يمكن للوسيط الذي يملك سياسة سعة خاصة أن يصدر 429 جديداً من حالته. ولا يمكنه إعادة عرض رفض قديم كمحتوى صالح. يبقى الحكم قرب المكوّن القادر على رؤية الرصيد الحالي.

ما يقوله الرمز فعلاً

لا يوثق 429 الهوية، ولا يثبت النية أو الإساءة، ولا يشهد بعدالة السياسة، ولا يضمن نجاحاً لاحقاً. كما لا يفرض على خادم تحت الهجوم أن ينفق طاقته في شرح كل رفض.

قيمته أضيق: يفصل سياسة التواتر عن فساد المحتوى وعن العجز العام، ويخبر العميل بأن التكرار الفوري لن يحل المشكلة غالباً. وعندما تسمح السعة، يمكن لشرح واضح ووقت صادق أن يجعلا العودة أهدأ.

لم يخترع HTTP الحصص. أعطى قرار توزيع محلي صوتاً مشتركاً، وترك سلطة ذلك الصوت محدودة بما يستطيع العداد إثباته.

المصادر