الخلاصة

  • تسمح bindings في WebDAV لعدة URIs بأن تصل إلى مورد واحد. وإذا كان المورد مجموعة، يكشف binding ثانٍ الأعضاء أنفسهم تحت مسار آخر وقد يصنع دورة تعود إلى سلف.
  • في PROPFIND واعٍ بالـ bindings مع Depth: infinity، يُبلّغ ظهور واحد للمجموعة بحالة 200 وتُسرد ذريته. تبقى المسارات اللاحقة في DAV:response بحالة 208 Already Reported، لكن الفروع التي سُردت لا تتكرر.
  • يضع DAV:resource-id هوية مورد ثابتة تحت المسارات المتغيرة. يحفظ العميل كل حافة binding ويوسع كل مجموعة مرة؛ وإذا لم يفهم 208، تنتهي الحلقة بـ 508 بدلاً من تسليم بنية ناقصة لا يعرف سبب نقصها.

بابان لا يصنعان مخزناً ثانياً

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

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

اختار 208 نتيجة أدق: سجّل الباب اللاحق، واربطه بهوية الغرفة التي سبق فتحها، ثم لا تكرر عدّ ما في الداخل.

الاختصار يقع على العمل، لا على علاقات فضاء الأسماء.

وضع WebDAV التفاصيل داخل 207 منذ البداية

يصف RFC 4918 الصادر عام 2007 حالة مجموعة WebDAV بأنها mappings بين مقاطع المسار والموارد، إضافة إلى خصائص المجموعة. اسم العضو إذن علاقة وصول وليس المورد نفسه.

تستخدم PROPFIND العمق 0 أو 1 أو infinity. يطلب العمق اللانهائي المجموعة وكل نسلها. ويأتي الرد العام 207 Multi-Status حاملاً قائمة مسطحة من عناصر DAV:response؛ يحدد كل href مساراً، وتحمل propstat حالات الخصائص المطلوبة.

لم تكن 207 الخارجية حكماً واحداً على التفاصيل. على العميل قراءة الجسم وحالاته الداخلية. وقد وفر هذا البناء المكان الدقيق لـ 208: فهي تصف ظهور binding بعينه في الكشف، ولا تقول إن طلب HTTP كله قد أُجيب عنه من قبل.

اعترف WebDAV الأساسي بإمكان امتلاك المورد أكثر من URI. ثم أضاف امتداد binding طريقة يخلق بها العميل مساراً جديداً إلى مورد قائم.

أنشأ BIND علاقة لا نسخة

عرّف RFC 5842، المنشور بوصفه Experimental في أبريل 2010، الطرق BIND وUNBIND وREBIND. تربط BIND مقطع مسار داخل مجموعة بمورد موجود، فتجعل URI الجديدة مدخلاً عادياً إلى الهدف نفسه.

الجديد هو الـ binding، لا المورد. وقد تحتفظ مجموعتان أبويتان بعلاقتين مستقلتين إلى الكائن نفسه.

تفرض binding integrity أن تستمر العلاقة وأن تشير إلى الهوية نفسها حتى تزيلها أو تغيرها عملية معرّفة صراحة. حذف حافة واحدة لا يجوز أن يفسد الأخرى أو يبرر استرجاع المورد ما دام له binding قائم.

الاسم البديل ليس مالكاً للكائن، لكنه ليس ملصقاً زائداً أيضاً. إنه جزء مستقل من حالة المجموعة الأم.

binding المجموعة أسقط ذريتها تحت بادئة جديدة

إذا كان الهدف مورداً ورقياً، تضيف العلاقة URI أخرى. وإذا كان مجموعة، يصبح أعضاؤها قابلين للوصول تحت بادئة المسار الجديدة، من غير نسخ bindings الداخلية لكل ابن.

وهكذا قد يزداد عدد URI mappings بينما يبقى عدد الموارد ثابتاً. وإذا ارتبطت مجموعة بنفسها أو بسلف، يمكن أن يتكرر مقطع المسار بلا نهاية.

يفرض RFC 5842 على الخادم كشف حلقات binding الخاصة بالمجموعات أثناء Depth: infinity. ويمكنه رفض إنشاء الحلقة أصلاً لأن دعم الحلقات اختياري. أما قبولها فيحوّل المشي من شجرة إلى graph traversal.

ليست البيانات المخزنة لانهائية. اللانهاية يصنعها خوارزم يعدّ كل مسار كائناً جديداً.

بقي resource-id ثابتاً حين تحركت العناوين

اختلاف URI لا يثبت اختلاف المورد، لأن الغرض من alias هو تعدد الطريق. كما أن تساوي المحتوى لا يثبت وحدة المورد؛ فقد يتساوى كائنان مستقلان اليوم ثم يفترقان لاحقاً.

يجعل RFC 5842 الخاصية DAV:resource-id إلزامية. تُعيّن عند خلق المورد، وتكون فريدة عبر جميع الموارد لكل الزمن، ولا تتغير عند تحديث المورد القائم أو نقله بـ REBIND، ولا يعاد استخدامها حتى بعد انعدام كل URI التي تصل إليه.

إذا أعاد مساران قيمتين متطابقتين حرفاً بحرف، علم العميل أنهما يصلان إلى كائن واحد. المعرّف لا يختار عنواناً canonical؛ إنه الهوية التي تبقى تحت العناوين.

بطلب الخاصية في PROPFIND، يستطيع العميل إعادة بناء الحواف وإثبات أن نسل المسار الثاني موجود في موضع آخر من الرد ولم يُفقد.

احتاج الاجتياز إلى دفترين

الدفتر الأول يسجل كل binding: المجموعة الأم، المقطع، href والهدف. والدفتر الثاني يسجل أي هويات مجموعة سبق توسيع نسلها في هذا الرد.

استعمال URI وحدها يحفظ الحواف لكنه يكرر العمل ويتبع الدورة. واستعمال resource-id وحده يوقف الحلقة لكنه قد يمحو حافة مشروعة قبل تسجيلها.

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

تربط 208 الدفترين: هذا المسار موجود؛ والمجموعة وراءه أعطت نسلها من ظهور آخر.

ظل الـ binding اللاحق في جسم الرد

نطاق 208 محدد: يمكن استخدامها داخل DAV:propstat في Depth: infinity. بين عدة bindings إلى المجموعة نفسها في النطاق، يحصل ظهور واحد على 200. وتبقى للظهورات اللاحقة عناصر DAV:response بحالة 208، لكن لا تُضاف ردود جديدة لذريتها.

لا يختفي href الثاني. وتربطه قيمة resource-id بالظهور السابق ذي 200.

في مثال RFC، يعيد /Coll/ و/Coll/Bar الهوية نفسها. الأول يأخذ 200 وتُسرد أعضاؤه، والثاني يأخذ 208. لا يستمر الخادم في /Coll/Bar/Bar لأنه عاد إلى العقدة ذاتها.

عبارة Already Reported تصف تاريخ التوسع في Multi-Status الحالي، ولا تمنح إذناً بإلغاء URI.

لم يتحول مسار 200 إلى صاحب شرعي

يجب اختيار ظهور واحد ليحمل التوسع حتى يبقى الرد محدوداً. لكن هذا الاختيار لا يجعله الأصل أو العنوان الدائم أو حاكم بقية العلاقات.

يبقى كل binding حالة لمجموعته الأم، وقد يحمل سياق تنقل وصلاحية وتدقيق مختلفاً. حذف مسارات 208 يمحو تلك الوقائع.

عندئذ قد تُفهم UNBIND كحذف للمورد بدل حذف حافة، أو تُمنح المجموعة التي احتوت المسار الأول سلطة وهمية على علاقات آباء آخرين.

أسبقية الاجتياز لا تتحول إلى سيادة على الاسم.

بقي 207 الغلاف الخارجي

على مستوى الطلب، يكون الرد عادة 207 Multi-Status. تظهر 208 في الجسم داخل نتيجة خصائص لمسار معين.

لذلك لا تعني أن العميل كرر طلب HTTP، ولا أن الرد كله أُرسل سابقاً. تقول فقط إن نسل هذه المجموعة سُرد في الوثيقة نفسها عبر binding آخر.

يحفظ href هوية المسار، ويصل resource-id المسارات بالكائن، وتبين 200/208 أين وقع التوسع.

الوسيط الذي يختزل كل ذلك إلى success=true ينقل الغلاف ويدمر أدلة graph الموجودة داخله.

احتاج الحذف إلى قدرة متفق عليها

قد يعني غياب الفرع أنه سُرد سابقاً أو أنه فُقد. لا يستطيع عميل يجهل 208 التمييز.

يعلن الخادم الداعم للـ bindings فئة الامتثال bind في ترويسة DAV لرد OPTIONS. وينبغي للعميل إرسال DAV: bind، وعندها يجب أن يفهم 208.

حماية للتوافق السابق، لا ينبغي استعمال 208 في Multi-Status من غير إشارة العميل. فقد يعامل برنامج قديم الحالة المجهولة كفشل أو يتصور أن المجموعة بلا أبناء.

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

أوقفت 508 ما سمحت 208 باستمراره

إذا واجه عميل غير واعٍ بالـ binding حلقة في PROPFIND عميق، يختار RFC 5842 حالة 508 Loop Detected. إن اكتُشفت قبل streaming أمكن أن تكون الحالة العليا؛ وإذا بدأ Multi-Status، يمكن التعبير عن الفشل في التفصيل.

مع 208 يواصل العميل المستعد: يحفظ الاسم البديل ولا يكرر الفرع. ومع 508 ينهي الخادم العملية لأنه واجه حلقة لانهائية، وتفشل العملية.

ليستا صياغتين لينة وقاسية لشيء واحد. الأولى مرجع مفهوم يسمح بالاستمرار؛ والثانية حد صريح عند غياب الفهم المشترك.

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

زادت الحواف سطح الهجوم أيضاً

يفتح BIND طريقاً جديداً إلى الحلقات العرضية أو العدائية. الكشف الإلزامي في العمق لا يحل كل استنزاف.

يذكر RFC 5842 مخاطر الخصوصية وdenial of service. قد توجه bindings العابرة للخوادم حملاً نحو هدف غير مستعد. وقد تكشف DAV:parent-set الاختيارية مواقع خاصة وتجبر الخادم على صيانة قوائم تتأثر من نطاقات إدارية أخرى.

تحد 208 تكراراً في رد واحد. لا تضع سقف CPU أو الذاكرة أو العقد أو الحجم، ولا تقرر من يملك خلق الحواف. حتى graph محدود قد يكون ضخماً.

تظل الطبقة المشتركة رقيقة: تعالج آلية تضخيم يمكن إثباتها، ولا تدعي أنها سياسة أمن كاملة.

المورد الواحد لا يمحو سياق الطريق

يثبت resource-id المشترك هوية الكائن، لكنه لا يفرض تطابق كل property عبر المسارات. لا تعتمد dead properties على عدد bindings أو الطريق، أما live properties فتتبع تعريفاتها وقد تحمل سياقاً متعلقاً بالمسار.

دمج كل المشاهدات بالهوية يمحو السياق. وعدّ كل اختلاف مورداً جديداً يمحو الهوية.

يلزم الفصل بين حقائق المورد وحقائق binding والمشاهدات المرتبطة بالطريق. تستعمل 208 الهوية المشتركة فقط لتقرير التوسع، لا لإلغاء بقية الطبقات.

يكون الدليل آمناً عندما لا تتجاوز سلطته ما يثبته فعلاً.

أبقى سجل IANA المعنى ضيقاً

يربط سجل IANA لرموز حالة HTTP حالة 208 Already Reported بـ RFC 5842. وتعرّف الوثيقة Experimental نفسها 508، بينما تشير 207 إلى RFC 4918.

لا يجعل التسجيل الامتداد Internet Standard، ولا يثبت انتشاره الحالي، ولا يحول 208 إلى رمز عام لتكرار صفوف قاعدة البيانات أو idempotency أو cache.

مكانها الدقيق WebDAV واعٍ بالـ bindings، وDepth infinity، وMulti-Status يفهمه العميل.

ضيق النطاق يحمي كلمة «already» من أن تصبح ترخيصاً لحذف كل ما يبدو متشابهاً.

كل الحواف، وتوسع واحد

لم يتظاهر HTTP 208 بأن graph شجرة. حفظ المسارات، وثبت هوية الكائن، وحدّ العمل.

يُبلّغ كل binding لأن الوصول حالة حقيقية. يحمل المورد ID ثابتاً لأنه لا ينتمي إلى URI واحدة. تُوسع الذرية مرة لأن تكرارها لا يضيف بنية. ويوضع status عند الحذف لأن الصمت بلا سبب يشبه ضياع البيانات.

لا يصبح مسار مركزاً سيادياً، ولا يتحول alias إلى نسخة، ولا تجبر دورة النظام على اختراع موارد لانهائية.

يبقى الباب الثاني في المخطط؛ ولا حاجة إلى عدّ خزائن الغرفة المشتركة مرة أخرى.