الخلاصة

  • يسرد Accept-Patch أنواع الوسائط المقبولة بوصفها وثائق تعديل. يدل وجوده على قدرة PATCH في المورد، لكنه لا يصادق على هوية الطالب ولا يمنحه حق الكتابة ولا يختار الصيغة ولا يثبت صلاحية تغيير بعينه.
  • اكتشاف القدرة ولغة الوثيقة وشرط الحالة والتفويض أربعة قرارات منفصلة. يساعد الحقل في إعداد طلب محتمل، أما البقية فتحسم عند وصول الطلب الفعلي في سياقه.

تعرض استجابة OPTIONS نوعي application/json-patch+json وapplication/merge-patch+json. عرف العميل أن المورد يعلن نحوين للتعديل. لم يعرف هل يحق لحسابه الكتابة، ولا هل النسخة التي قرأها ما زالت جارية، ولا هل تسمح قواعد العمل بالعمليات. ولم يحصل على وثيقة اعتماد.

ينشأ الخطأ عندما تختصر هذه المعلومة الرسمية إلى قيمة واحدة اسمها «قابل للتعديل». فالحقل صادر عن الخادم ومسجل ويظهر قرب Allow، لكن RFC 5789 يفصل إعلان الصيغ عن واجب تفويض الطلبات.

قدرة المورد ليست حقاً لكل طالب

جاء PATCH لأن PUT يعني الاستبدال الكامل، بينما يحتاج التغيير الجزئي إلى تعليمات يحدد نوع الوسائط معناها. يحدد URI الهدف المورد، ويحدد Content-Type لغة الوثيقة، ويربط الشرط العملية بحالة شوهدت، ثم تقرر المصادقة وضبط الوصول هل يجوز للفاعل التنفيذ.

يسبق Accept-Patch تلك القرارات. قيمته قائمة أنواع وسائط بمعاملات اختيارية. ينبغي أن يظهر في OPTIONS لمورد يدعم PATCH. وإذا ظهر في رد على أي طريقة، دل ضمناً على السماح بـPATCH كقدرة للمورد، ودل كل نوع مدرج على قبول تلك الصيغة هناك.

لا يعني «السماح» تفويض الجميع. فقسم الأمن في RFC 5789 يذكر التفويض وضبط الوصول والمصادقة بصورة مستقلة. لذلك قد يعلن GET عام الصيغ، بينما يعيد PATCH المجهول 401 أو 403. وقد يرى حسابان القائمة نفسها ويملكان نطاقي تعديل مختلفين.

يمكن أن يظهر PATCH في Allow من دون Accept-Patch؛ عندئذ تعلن الطريقة ولا تعلن الصيغ. كما يقول RFC 9110 إن مجموعة الطرق الفعلية تحدد وقت كل طلب وقد تتغير ديناميكياً. الاكتشاف ملاحظة مؤقتة، لا حجزاً للمورد.

نوع الوسائط هو الذي يحدد البرنامج

لا توجد صيغة افتراضية ملزمة لكل تطبيق. على الخادم التأكد من ملاءمة الوثيقة للهدف. ويوضح التصويب الموثق 3169 أن دلالة PATCH تأتي من نوع الوسائط؛ فلا يجوز اختراع دلالة تعديل لـapplication/json أو application/xml لمجرد القدرة على تحليلهما.

يستخدم JSON Patch النوع application/json-patch+json ومصفوفة مرتبة من عمليات add وremove وreplace وmove وcopy وtest. أما JSON Merge Patch فيستخدم application/merge-patch+json، ويشبه المستند الهدف، ويحدد الإضافة والاستبدال بالمقارنة ويجعل null علامة حذف.

كلاهما JSON لكنهما غير متبادلين. تستطيع test حماية افتراض محدد، بينما يناسب Merge Patch الأجسام أكثر ولا يلائم البنى التي تعتمد قيمة null الحقيقية أو تحرير المصفوفات بدقة. إعلان الصيغتين لا يسمح بالتحويل الآلي ولا يجعل ترتيب القائمة تفضيلاً عاماً.

يختار العميل الصيغة قصداً ويعلنها في Content-Type. تغيير اسم النوع فوق جسم مكتوب بلغة أخرى لا يصلح الوثيقة.

يمكن أن يصاحب الإعلان رفضاً

الصيغة المدعومة لا تضمن نجاح الطلب. قد ينتج 400 عن وثيقة سيئة البنية، و415 عن نوع غير مدعوم، و422 عن تعليمات صحيحة تركيبياً غير قابلة للمعالجة، و404 عن مورد غائب لا تقبل الصيغة إنشاءه، و409 عن تعارض حالة أو تزامن، و412 عن فشل شرط صريح.

ينبغي لرد 415 أن يتضمن Accept-Patch. يرفض الخادم المحاولة ويعرض بدائل في الوقت نفسه. لا يقبل الحقل الوثيقة بأثر رجعي، ولا يسمح بتغيير Content-Type وحده، ولا يَعِد بأن الطلب التالي سيتجاوز التفويض وقواعد العمل.

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

If-Match يحمي الحالة لا الامتياز

قد تفسد التعديلات المبنية على نسخة معروفة إذا سبقها تعديل آخر. لذلك يوصي RFC 5789 بطلب شرطي ويضرب مثلاً بـETag قوي داخل If-Match.

يفرض RFC 9110 تقييم If-Match بالمقارنة القوية قبل الطريقة. إذا تغيرت النسخة، يمنع 412 الخادم من تخمين إعادة تطبيق الوثيقة. لكن ETag ليس سراً ولا إذناً؛ قد يعرفه غير المصرح له، وقد يقدم المصرح له قيمة قديمة. يجب تقييم الحالة والوصول منفصلين.

يسجل IANA طريقة PATCH على أنها غير آمنة وغير تكرارية الأثر. يمكن بناء طلب معين ليكون تكراري الأثر، لكن ذلك يعتمد على عملياته. لا تصف قائمة الصيغ نتيجة إعادة وثيقة مستقبلية.

الذرية تخص التنفيذ

يجب على الخادم تطبيق التغييرات كلها أو لا شيء. لا يجوز إظهار حالة جزئية، وإذا فشلت الوثيقة فلا يبقى أي تغيير. يوضح RFC 6902 أن فشل عملية test يلغي JSON Patch كله.

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

يفصل التصميم الجيد بين المصادقة، وتفويض الهدف والعمليات، والتحقق من Content-Type، وتحليل اللغة، وتقييم If-Match وقواعد المجال، ثم الالتزام الذري. قراءة Accept-Patch لا تبدأ معاملة ولا تقفل نسخة.

التخزين والتوقيع لا يغيران المعنى

يفرض RFC 9111 على التخزين المؤقت الذي مر به طلب غير آمن ناجح إبطال استجابات الهدف. وقد يكون Location وContent-Location من الأصل نفسه مرشحين، لا عنواناً من أصل آخر. يأتي ذلك بعد PATCH فعلي، لا بعد OPTIONS يحمل الإعلان، ولا يضمن إبطالاً عالمياً.

ويسمح RFC 9421 بتوقيع مكونات مختارة. يمكن لتغطية Accept-Patch حماية سلامة الإعلان وأصالته ضمن ملف تطبيق، لكنها لا تنشئ قرار الوصول. يحتاج التفويض إلى قواعد إضافية تربط الهوية والطريقة والهدف والمحتوى.

نموذج قابل للتدقيق

ينبغي للعميل فصل URI ووقت الملاحظة، وإشارة الطريقة، والأنواع والمعاملات، ومحقق نسخة الأساس، وسياق الهوية. ويستطيع الخادم الإعلان عبر OPTIONS، ثم عند وصول PATCH يصادق ويفوض ويتحقق من النوع والشرط وينفذ ذرياً.

تشمل الاختبارات Allow بلا قائمة، والقائمة في GET، والإعلان نفسه لحسابات مختلفة، وIf-Match قديماً، ورفض JSON العام، واختلاف أثري صيغتي JSON، وفشل test بلا تغيير، وإعلاناً موقعاً يتبعه 403.

تعرض صفحة التصويبات الحالية ثلاث حالات موثقة وواحدة مرفوضة. يحذف التصويب 5521 Content-Location من مثال 204، ويصحح 7513 رابطاً فقط، ولا يغير التصويب المرفوض 3419 القاعدة.

المصادر