تفتح مقالا في مدونة لتقرا التعليقات المكتوبة تحته، ثم تكتب تعليقك الخاص وتضغط زر النشر. في الحالتين يرسل المتصفح رسالة طلب الى الخادم، ويكتب في اول سطر منها كلمة تحدد ما يريده تحديدا، تسمى هذه الكلمة طريقة الطلب (HTTP request method).
عند قراءة الصفحة تكون هذه الطريقة GET، وعند نشر التعليق تكون POST. ويظهر الفارق الجوهري بينهما فور تكرار الطلب؛ اذ يمكنك اعادة تحميل صفحة المقال عشر مرات دون ان يتبدل محتواها او ينشا اي تغيير على الخادم. اما اذا ضغطت زر نشر التعليق مرتين متتاليتين لتاخر استجابة الشبكة، فقد ينشر الخادم تعليقك مرتين متطابقتين.
يعي المتصفح هذا الفارق تماما؛ فهو يعيد طلب صفحة المقال متى اردت دون تحذير، بينما اذا اردت تحديث صفحة جاءت اثر ارسال نموذج، يوقفك المتصفح برسالة تنبيه تسال عما اذا كنت تريد اعادة ارسال البيانات مرة اخرى. وتتبع هذه السلوكيات قواعد ثابتة يحددها معنى كل طريقة، وهي القواعد نفسها التي تتيح لك معرفة ما اذا كان اي طلب شبكي قابلا لاعادة المحاولة بامان.

الطريقة: كلمة تقول ماذا تريد من المورد
يحدد كل طلب HTTP امرين رئيسيين: المورد الذي يقصده العميل، وما يريد فعله بهذا المورد. يحدد الهدف (request target) المورد عبر المسار والاستعلام، بينما تحدد الطريقة نوع الاجراء المطلوب. وفي بروتوكول HTTP/1.1 تاتي الطريقة دائما في الكلمة الاولى من سطر الطلب:
GET /articles/http-methods/comments HTTP/1.1الكلمة GET هنا هي طريقة الطلب، والمسار /articles/http-methods/comments هو هدف الطلب الذي يمثل قائمة التعليقات التابعة لمقال محدد. ومجموع هذا السطر يعني للخادم: ارسل نسخة من قائمة التعليقات هذه.
يشبه هذا التبادل تسليم بطاقة طلب الى موظف ارشيف؛ اذ تدون على البطاقة رقم الملف الذي تريده، وتختار معه فعلا واحدا من قائمة افعال موحدة ومحددة سلفا يفهمها كل موظف: «ارني»، او «اضف اليه»، او «ضع هذه النسخة مكانه»، او «عدل فيه»، او «ازله». رقم الملف هنا يمثل هدف الطلب، بينما يمثل الفعل المختار طريقة الطلب.
تبقى قائمة الافعال هذه موحدة وثابتة لجميع الملفات، فلا يحتاج موظف الارشيف الى دليل اوامر خاص بكل ملف على حدة. كذلك هو الحال في بروتوكول HTTP؛ اذ تمنح المواصفة القياسية كل طريقة معنى دلاليا موحدا وثابتا ايا كان نوع المورد المستهدف، سواء كان صفحة نصية او ملف صورة او سجلا في قاعدة بيانات. وبفضل هذا التوحيد، تستطيع المتصفحات ومحركات البحث والوسائط البرمجية فهم ما يقصده الطلب والتعامل معه استنادا الى طريقته، دون حاجة الى معرفة مسبقة بالقواعد الداخلية للموقع الذي يستقبل الطلب.
وتعتمد الامثلة التوضيحية في هذا الدرس على مدونة افتراضية تعمل على النطاق blog.example.com، وتتعامل مع موردين اثنين: قائمة التعليقات الملحقة بالمقال عند العنوان /articles/http-methods/comments، وتعليق فردي محدد عند العنوان /comments/17.
GET: أعطني نسخة من المورد
تطلب الطريقة GET من الخادم اعادة تمثيل للمورد المستهدف بحالته الراهنة. وهي اكثر طرق البروتوكول استخداما على الاطلاق؛ فحين تنقر رابطا تشعبيا، او يحمل المتصفح صورة معروضة داخل الصفحة، يرسل المتصفح طلب GET الى الخادم.
وهذا طلب كامل لاسترجاع قائمة التعليقات:
GET /articles/http-methods/comments HTTP/1.1
Host: blog.example.comيعلن السطر الاول الرغبة في الحصول على نسخة من قائمة التعليقات، بينما يحدد سطر الترويسة التالي اسم المضيف الذي يستضيف المورد. ولا يتضمن هذا الطلب جسما للرسالة، لان العميل يريد جلب بيانات من الخادم فقط ولا ينقل اليه بيانات لمعالجتها.
ولا يطلب العميل بطريقة GET من الخادم اجراء اي تعديل على حالة المورد؛ ولذلك فان ارسال هذا الطلب مرة واحدة او عشر مرات يقتصر في كل مرة على طلب القراءة ذاتها دون تغيير.
واذا احتاج العميل الى تخصيص ما يطلبه، كطلب الصفحة الثانية من قائمة التعليقات مثلا، فانه يمرر هذا الخيار ضمن نص الاستعلام في الرابط: GET /articles/http-methods/comments?page=2، ولا يرسله في جسم الطلب. فالمواصفة القياسية للبروتوكول لا تمنح وجود جسم في طلبات GET اي دلالة معيارية لمعالجة المورد، كما ان بعض البرمجيات والخوادم الوسيطة ترفض طلبات GET التي تحمل جسما او تتجاهل محتواه تماما.
POST: خذ هذه البيانات وعالجها
حين يضغط المستخدم زر النشر بعد كتابة تعليقه، لا يطلب المتصفح نسخة من مورد موجود، بل يحمل نص التعليق الى الخادم ويطلب منه معالجته وفق قواعده. وهنا ياتي دور الطريقة POST؛ اذ ترسل البيانات داخل جسم الطلب ليتولى المورد المستهدف معالجتها وفق منطقه البرمجي الخاص.
وهذا طلب لنشر تعليق جديد تحت المقال:
POST /articles/http-methods/comments HTTP/1.1
Host: blog.example.com
Content-Type: application/json
Content-Length: 38
{"name":"Sara","text":"Useful lesson"}- السطر الاول: يستهدف قائمة التعليقات ذاتها التي طلبها العميل سابقا للقراءة، لكنه يستهدفها هنا بطريقة POST، مما يعني: استقبل هذه البيانات وعالجها وفق قواعد هذه القائمة.
- الترويستان التاليتان: تصفان محتوى الجسم؛ اذ تبين
Content-Typeان البيانات مكتوبة بصيغة تدوين كائنات جافاسكريبت (JavaScript Object Notation, JSON)، بينما تبينContent-Lengthان طول محتوى الجسم يبلغ 38 بايت. - جسم الطلب بعد السطر الفارغ: يحمل محتوى التعليق ذاته. وتمثل صيغة JSON نسقا نصيا شائعا لتمثيل البيانات في هيئة ازواج من المفاتيح والقيم. ويظهر هنا زوجان: المفتاح
nameلاسم الكاتب، والمفتاحtextلنص التعليق.
تعالج قائمة التعليقات هذه البيانات باضافة تعليق جديد الى محتواها. وفي هذه الحالة يتولى الخادم تخصيص رقم مميز وعنوان مستقل لهذا التعليق الجديد، مثل /comments/17، ويخطر العميل به عادة في رسالة الاستجابة. فالعميل لم يكن يعلم هذا العنوان قبل ارسال طلبه.
ولا تقيد المواصفة القياسية ما يجب ان يفعله الخادم بالبيانات الواردة اليه في طلب POST؛ اذ يرجع ذلك الى الوظيفة المحددة للمورد البرمجي، فقد ينشئ المورد سجلا جديدا، او يرسل رسالة بريدية، او يعالج عملية دفع الكتروني. ولهذا تعد POST اكثر طرق البروتوكول مرونة واتساعا في الدلالة.
واذا وصل هذا الطلب بعينه الى الخادم مرتين، ستضيف القائمة تعليقين متطابقين في المحتوى لكنهما يحملان معرفين مختلفين، مثل 17 و18؛ لان كل طلب POST في هذا السياق يعني امرا بالاضافة الجديدة، ولا يعني ضبط القائمة على حالة نهائية بعينها.
وتسمى حقول الادخال التي يملاها المستخدم في صفحة الويب ثم يرسلها عبر المتصفح بالنموذج (form). وتقتصر النماذج في لغة HTML على استخدام احدى طريقتين فقط عند ارسالها: GET او POST. اما بقية الطرق التي سنتناولها تاليا، فلا ترسلها المتصفحات عبر نماذج HTML الافتراضية، بل ترسلها البرمجيات عبر نصوص جافاسكريبت داخل الصفحة، او عبر تطبيقات الهواتف الذكية، او عبر ادوات سطر الاوامر مثل أداة curl.
PUT: ضع هذه النسخة كاملة في هذا العنوان
اذا رغب كاتب التعليق في تصحيح نصه بعد نشره، يصبح عنوان المورد معروفا للعميل بدقة: /comments/17. وتفيد الطريقة PUT بابلاغ الخادم بامر صريح: اجعل المورد الموجود في هذا العنوان مطابقا تماما للتمثيل المرفق في الطلب؛ بحيث يحل هذا التمثيل محل اي محتوى كان موجودا في ذلك العنوان من قبل.
PUT /comments/17 HTTP/1.1
Host: blog.example.com
Content-Type: application/json
Content-Length: 43
{"name":"Sara","text":"Very useful lesson"}يستهدف السطر الاول التعليق رقم 17 مباشرة، لا قائمة التعليقات العامة. ويحمل جسم الطلب نسخة كاملة من بيانات التعليق تتضمن الاسم والنص المعدل معا. فاذا نجحت معالجة الطلب، اصبحت حالة المورد 17 مطابقة تماما لهذه النسخة المرسلة، بحيث اذا استرجعه العميل لاحقا بطلب GET، فستصله هذه النسخة المحدثة.
واذا ارسل العميل طلب PUT الى عنوان لا يحتوي على مورد قائم من قبل، فان دلالة PUT تتيح للخادم انشاء مورد جديد في ذلك العنوان المحدد بالبيانات المرفقة، اذا كانت قواعد الخادم تسمح للعميل بتحديد عناوين الموارد المنشاة.
ويتلخص الفرق الجوهري بين POST وPUT في نقطتين اساسيتين:
- الجهة التي تحدد عنوان المورد: في طلب POST يرسل العميل البيانات الى مورد تجميعي مثل قائمة التعليقات، ويتولى الخادم تحديد عنوان التعليق الجديد المنشا. اما في طلب PUT فان العميل هو الذي يحدد في سطر الطلب العنوان النهائي للمورد المستهدف بالتعديل او الانشاء.
- دلالة البيانات المرسلة: تمثل البيانات في POST مدخلات موجهة لمعالجة المورد وفق قواعده الداخلية، بينما تمثل البيانات في PUT الحالة النهائية الكاملة التي يجب ان يستقر عليها المورد في ذلك العنوان.
ولان PUT تستبدل المورد القائم استبدالا شاملا بالنسخة المرسلة، يجب ان يتضمن جسم الطلب التمثيل الكامل للمورد دون نقصان. فلو ارسل العميل نص التعليق فقط في جسم الطلب متجاهلا حقل الاسم:
{"text":"Very useful lesson"}فان هذه النسخة تفتقر الى حقل الاسم؛ مما يؤدي اما الى حذف حقل الاسم من السجل على الخادم لانه لم يرد في النسخة البديلة، واما الى رفض الخادم للطلب بسبب وصول تمثيل ناقص لا يستوفي شروط المورد. فمعنى PUT في البروتوكول هو الاستبدال الكامل للتمثيل، وليس تعديل الحقول المذكورة والابقاء على غيرها؛ اذ يفرد البروتوكول لتلك الغاية طريقة مستقلة اخرى.
PATCH: عدل هذا الجزء وحده
يعد ارسال النسخة الكاملة للمورد مقبولا وعمليا عندما يكون حجم المورد صغيرا مثل تعليق قصير. اما في الموارد المعقدة التي تتالف من عشرات الحقول المتنوعة، مثل ملف بيانات مستخدم كامل، فان اعادة ارسال المورد بكل حقوله لتعديل حقل واحد يمثل هدرا لحركة البيانات على الشبكة ويثقل كاهل الخادم والعميل دون مبرر. وفضلا عن ذلك، فان اي حقل يغفل العميل تضمينه في النسخة المرسلة بطلب PUT يصبح مهددا بالضياع.
لتجاوز هذا القيد، وضعت المواصفة القياسية الطريقة PATCH؛ اذ يرسل العميل عبرها وثيقة تصف التعديلات المطلوبة فقط، بدلا من اعادة ارسال التمثيل الكامل للمورد.
PATCH /comments/17 HTTP/1.1
Host: blog.example.com
Content-Type: application/json
Content-Length: 29
{"text":"Very useful lesson"}يقصد السطر الاول التعليق 17 بالطريقة PATCH، ومعناه: طبق هذا التعديل المحدد على المورد القائم. وهنا نرى الجسم ذاته الذي كان معيبا وناقصا في طلب PUT، لكن دلالته الوظيفية اختلفت تماما؛ فالطلب لا يدعي انه يقدم النسخة الكاملة الجديدة للتعليق، بل يحمل وصفا للتغيير: عدل قيمة الحقل text لتصبح النص المرفق. وبما ان حقل الاسم لم يرد ذكره في وثيقة التعديل، فانه يظل محفوظا في الخادم بحالته السابقة دون تغيير.
وتقتصر دلالة الطريقة PATCH على امر التعديل الجزئي المجرد، دون ان تفرض المواصفة صيغة موحدة محددة لكتابة وثيقة التغيير، بل يحدد الخادم صيغ التعديل المقبولة لديه. ففي هذا المثال البسيط يعامل الخادم مدخلات JSON بوصفها تعديلا مباشرا للحقول المذكورة مع الابقاء على غيرها. بينما توجد صيغ قياسية اخرى تعبر عن التعديل في هيئة سلسلة من التعليمات الاجرائية، مثل اوامر «اضف قيمة»، او «احذف عنصرا»، او «استبدل حقلا».
وبالعودة الى تشبيه موظف الارشيف: تمثل PUT تسليم ورقة كاملة لتحل محل وثيقة الملف القديمة باسرها، بينما تمثل PATCH تسليم مذكرة تعديل صغيرة تنص على: «استبدل السطر الثاني فقط في الملف رقم 17 بالنص الاتي، واترك باقي الوثيقة كما هي».
DELETE: أزل هذا المورد
تطلب الطريقة DELETE من الخادم ازالة المورد المرتبط بالعنوان المحدد في الطلب. ولا يحتاج هذا الطلب عادة الى تضمين جسم للرسالة، اذ يكفي تحديد عنوان المورد في سطر الطلب لبيان المطلوب:
DELETE /comments/17 HTTP/1.1
Host: blog.example.comيعلن السطر الاول امرا صريحا: احذف التعليق رقم 17 من هذا العنوان. فاذا اكتملت معالجة الطلب بنجاح، ثم حاول العميل استرجاع العنوان نفسه لاحقا بطلب GET، يرد الخادم في المعتاد برمز الحالة 404، دلالة على ان المورد المطلوب لم يعد موجودا في ذلك العنوان.
وتعني DELETE في مواصفة البروتوكول فك ارتباط المورد بالعنوان المذكور وازالته من نطاق الوصول عبر الشبكة، ولا تشترط المواصفة محوا ماديا فوريا للبيانات من وسائط التخزين لدى الخادم. فللخادم كامل الحرية في حذف السجل نهائيا، او الاكتفاء بوسمه بالحذف المنطقي، او ارشفته في قاعدة بيانات داخلية؛ اذ يمثل ذلك قرارا تطبيقيا داخليا للخادم لا تتدخل المواصفة في فرضه.
الطريقة إعلان نية، والخادم هو الذي ينفذ
تعلن طريقة الطلب ما يرغب العميل في تنفيذه، لكنها لا تفرض التنفيذ فرضا جبريا على الطرف الاخر؛ اذ يبقى البرنامج المشغل للخادم هو صاحب القرار النهائي في كيفية معالجة كل رسالة ترد اليه. ويستطيع هذا البرنامج ان ينفذ الحذف المطلوب عند استقبال طلب DELETE التزاما بدلالة الطريقة، كما يستطيع رفض الطلب او تجاهله او حتى تنفيذ اجراء مغاير تماما. وفي مثال الارشيف: تطلب البطاقة سحب الملف، لكن موظف الارشيف هو الذي يملك سلطة تنفيذ السحب او رفضه تبعا للصلاحيات وقواعد العمل لديه.
وتظهر خدمة الصدى التفاعلية httpbin هذا المبدأ بجلاء؛ اذ يقبل العنوان العام /anything فيها استقبال اي طريقة كانت، ولا يطبق اي تغيير على اي بيانات، بل يقتصر دوره على اعادة قراءة الطلب وطباعة تفاصيله في نص الاستجابة:
curl -i -X DELETE https://httpbin.org/anything/comments/17HTTP/2 200
content-type: application/json
...
{
...
"method": "DELETE",
"url": "https://httpbin.org/anything/comments/17"
}يحدد خيار سطر الاوامر -X استخدام الطريقة DELETE صراحة. ويرد الخادم برمز الحالة 200 مشيرا الى نجاح المعالجة، ويؤكد في جسم الاستجابة استلام الطريقة عبر "method": "DELETE". ومع ذلك لم يقع اي حذف فعلي لاي مورد، اذ لا توجد تعليقات مخزنة في هذا العنوان اصلا. فرمز الحالة 200 يخبر العميل بان الخادم عالج رسالة الطلب بنجاح وفق منطقه الخاص، ولا يقدم ضمانا مستقلا بان حدث الحذف المادي قد وقع بالفعل على اقراص الخادم.
وفي المقابل، قد يرفض المورد البرمجي طريقة لا يدعمها تصميمه. فعلى سبيل المثال، يرفض العنوان المخصص /delete في الخدمة ذاتها استقبال طلبات القراءة بطريقة GET:
curl -i https://httpbin.org/deleteHTTP/2 405
...
allow: OPTIONS, DELETE
...
...
<title>405 Method Not Allowed</title>
...توضح هذه الاستجابة عنصرين معياريين في التعامل مع الطرق المرفوضة:
- رمز الحالة 405 (Method Not Allowed): يفيد بان الخادم يفهم الطريقة GET ويدرك معناها العام، لكن المورد المحدد في هذا المسار لا يسمح باستخدامها معه.
- ترويسة السماح (
Allowheader): تسرد قائمة الطرق التي يدعمها هذا المورد تحديدا، وهي في هذا المثال OPTIONS وDELETE. وتلزم المواصفة القياسية الخادم بارسال ترويسةAllowدائما عند الرد بالرمز 405، بينما تجيز له تضمينها اختياريا في استجابات اخرى لاطلاع العميل على الخيارات المتاحة.
يتبين من ذلك ان دلالة كل طريقة تمثل اتفاقا معياريا موثقا في مواصفات بروتوكول HTTP، يلتزم به الخادم طوعا لدعم المعايير المشتركة للشبكة. والتزام الخوادم بهذا المعنى المشترك هو الاساس الذي يمكن البرمجيات المستقلة — كالمتصفحات ومحركات البحث ووكلاء الشبكة — من التعامل مع مختلف المواقع والاعتماد على تصرفاتها بثقة، استنادا الى خاصيتين جوهريتين تصف بهما المواصفة كل طريقة من طرق البروتوكول.
الطرق الآمنة (safe): طلب لا يطلب تغيير شيء
تشغل محركات البحث برمجيات الية تجوب مليارات صفحات الويب وتستكشف الروابط التشعبية وتطلبها تباعا، وتعرف هذه البرمجيات باسم الزواحف (web crawlers). وتطبق بعض المتصفحات الحديثة تقنية تسمى الجلب المسبق (prefetching)؛ اذ تطلب موارد الروابط المحتملة قبل ان ينقر عليها المستخدم فعليا، لتفتح الصفحة امامه لحظيا عند النقر. ترسل هذه البرمجيات طلبات شبكية لم يامر المستخدم باطلاقها صراحة في تلك اللحظة، فكيف تضمن تلك الانظمة جلب تلك الصفحات دون احداث اضرار غير مقصودة او تعديل بيانات المواقع؟
يكمن الجواب في ان هذه البرمجيات تحصر طلباتها التلقائية في استخدام الطريقة GET وحدها، وتعتمد اعتمادا كاملا على دلالتها المعيارية. فطلب GET بطبيعته طلب قراءة واسترجاع مجرد؛ لا يطلب العميل من خلاله اجراء اي تعديل على حالة الخادم، ولا يتوقع حدوث ذلك التغيير. وتسمى كل طريقة تحمل هذا المعنى دلاليا بالطريقة الامنة (safe method).
ومن بين الطرق الخمس الاساسية التي تناولناها، تنفرد GET بكونها الطريقة الامنة الوحيدة. وتعد الطريقة HEAD طريقة امنة ايضا، لانها تطابق طلب GET في جميع جوانبه الدلالية مع استثناء وحيد هو ان الخادم يعيد ترويسات الاستجابة دون ان يرفق معها جسم المحتوى. في المقابل، تصنف الطرق POST وPUT وPATCH وDELETE بوصفها طرقا غير امنة (unsafe)، لان كل طلب منها يدعو الخادم الى احداث تغيير مقصود في حالة الموارد لديه.
ولا تعني صفة «الامان» هنا ان الخادم يمتنع تماما عن تنفيذ اي نشاط برمجي او كتابة اي بيانات عند ورود الطلب. فاغلب خوادم الويب تسجل كل طلب واصل في ملفات السجلات التشغيلية (access logs)، كما تزيد كثير من المواقع عداد مشاهدات المقال عند كل قراءة. تمثل هذه التغييرات اثارا جانبية واقعية، لكنها اثار تخص الخادم وحده ولم تكن مطلبا مقصودا من العميل. فخاصية الامان تصف ما يطلبه العميل ويتحمل مسؤوليته الدلالية، ولا تحكم على التفاصيل الفنية الداخلية لادارة الخادم.
ويتجلى الثمن الفادح لاختراق هذا الاتفاق المعياري حين يخالفه مطور موقع. فلو وضعت مدونة زرا لحذف التعليق تحت كل مشاركة، وجعلت هذا الزر يرسل طلبا بالصيغة التالية:
GET /comments/17?do=delete HTTP/1.1
Host: blog.example.comفان هدف الطلب في هذا المثال يحمل في نص الاستعلام امرا صريحا باجراء الحذف، مع ان الطريقة المستخدمة هي GET. ولو حاول مطور الموقع تامين هذا الاجراء بعرض نافذة تاكيد تسال الزائر «هل انت متاكد من رغبتك في الحذف؟»، فلن تحمي هذه النافذة بيانات التعليق على الاطلاق. فالبرمجيات الالية التي تطبق الجلب المسبق في متصفح صاحب الحساب لا تشاهد واجهة المستخدم ولا تنقر على نوافذ التاكيد؛ بل تقرا الرابط مباشرة من نص الصفحة وتطلبه فورا عبر الشبكة، فيستقبل الخادم طلب GET ويحذف التعليق دون اي تدخل بشري.
وقد وقعت هذه الكارثة التقنية بصورة واسعة عام 2005، عندما اطلقت شركة Google اداة مساعدة لتسريع التصفح باسم Google Web Accelerator؛ اذ كانت تلك الاداة تعمل وسيطا محليا في متصفح المستخدم وتجلب مسبقا روابط الصفحات المعروضة عبر طلبات GET متتالية. ولما كانت كثير من تطبيقات الويب انذاك تعتمد على طلبات GET لحذف البيانات وسحب الاشتراكات ومسح المشاركات، طلبت الاداة تلك الروابط تلقائيا، مما اسفر عن حذف بيانات واسعة وسجلات حساسة من حسابات الاف المستخدمين دون ان يضغط احد منهم على اي زر للحذف.
وتحمل المواصفة القياسية مسؤولية مثل هذه الحوادث كاملة على عاتق مطور الموقع؛ فاذا كان الرابط ينفذ اجراء يغير حالة الموارد، وجب عليه معماريا منع تنفيذ ذلك الاجراء عند طلبه عبر طرق امنة. اما برمجيات العميل التي ارسلت طلب GET، فقد تصرفت وفق المعيار الدلالي المعتمد ولم تطلب سوى القراءة والاسترجاع.
ثبات الأثر عند التكرار (idempotency)
تخيل انك نقرت زر النشر لارسال مشاركتك، فاخذ مؤشر التحميل يدور في المتصفح، ثم انقطع الاتصال الشبكي فجاة قبل ان يرجع الخادم اي جواب. هل وصلت رسالتك الى الخادم ام تعثرت في الطريق؟ لا سبيل لمعرفة ذلك على وجه اليقين؛ فقد يكون الطلب قد فقد في الشبكة قبل الوصول، او لعله وصل بالفعل واضاف الخادم التعليق ثم انقطع الاتصال اثناء عودة رسالة الاستجابة. في هذا الموقف المعلق، يميل المستخدم تلقائيا الى اعادة المحاولة وضغط الزر مرة ثانية، مما يطرح سؤالا تقنيا جوهريا: ما الاثر المترتب على وصول الطلب نفسه مرتين متتاليتين الى الخادم؟
تتولى الاجابة عن هذا التساؤل الخاصية المعيارية الثانية لطرق البروتوكول. فاذا كان ارسال الطلب نفسه عدة مرات متتالية يترك الخادم في الحالة النهائية ذاتها التي يتركه فيها ارساله مرة واحدة فقط، فان طريقة الطلب تسمى طريقة ثابتة الاثر (idempotent method)، وتسمى الخاصية نفسها ثبات الاثر عند التكرار (idempotency).
ويتضح اثر تكرار كل طلب في مثال التعليقات عبر الجدول الاتي:
| الطلب | بعد المرة الاولى | بعد المرة الثانية | هل الطريقة ثابتة الاثر؟ |
|---|---|---|---|
PUT /comments/17 بالنص الجديد |
اصبح نص التعليق مطابقا للنسخة الجديدة | يظل نص التعليق مطابقا للنسخة الجديدة ذاتها | نعم |
DELETE /comments/17 |
حذف التعليق من موقعه، ورد الخادم بالرمز 200 | لم يجد الخادم ما يحذفه، ورد بالرمز 404 | نعم |
POST /articles/http-methods/comments |
اضيف التعليق رقم 17 الى القائمة | اضيف تعليق جديد برقم 18 بالنص نفسه | لا |
في طلب PUT، يستبدل الطلب الثاني نسخة المورد بنسخة اخرى مطابقة لها حرفيا، فتبقى البيانات النهائية على الخادم بلا اي تغيير اضافي. وفي طلب DELETE، يزيل الطلب الاول المورد من عنوانه، بينما لا يجد الطلب الثاني شيئا لحذفه فيرد الخادم برمز الحالة 404. وهنا اختلفت استجابة الخادم بين المرتين، لكن الحالة الراهنة على الخادم ظلت كما هي تماما: المورد رقم 17 غير موجود بعد الطلب الاول وبعد الطلب الثاني على حد سواء. اما في طلب POST، فان كل استدعاء يعبر عن امر باضافة جديدة، فينتج عن تكراره انشاء سجلين منفصلين ومضاعفة المحتوى.
ولا تصنف المواصفة القياسية الطريقة PATCH بوصفها طريقة ثابتة الاثر، لان اثرها النهائي يرتبط بطبيعة وثيقة التعديل المرفقة في الطلب. فاذا تضمنت الوثيقة امرا من قبيل «اضبط قيمة هذا الحقل لتكون كذا»، فان تكرار الطلب سينتج الحالة ذاتها ويكون ثابتا في الاثر. اما اذا نصت الوثيقة على اجراء من قبيل «الحق هذا السطر في نهاية النص القائم»، فان كل تكرار للطلب سيضيف سطرا جديدا ويضاعف التغيير على الخادم. وبما ان الطريقة PATCH لا تحدد نمط التعديل سلفا ولا تلزم العميل بصيغة معينة، يمتنع افتراض ثبات اثرها بصورة تلقائية عامة.
وتعد جميع الطرق الامنة ثابتة الاثر بالضرورة؛ فالطلب الذي لا يطلب احداث اي تغيير في المرة الاولى، لن يطلب اي تغيير اذا كررته عشرات المرات. وكما هو الحال في خاصية الامان، ينصب حكم ثبات الاثر على ما طلبه العميل لا على النشاط الداخلي للخادم؛ فاذا دون الخادم سجلا لكل طلب PUT يرد اليه، يظل طلب PUT محتفظا بصفة ثبات الاثر لان بيانات المورد نفسه لم تتغير بتكرار الطلب.
الطرق وخاصيتاها في جدول واحد
| الطريقة | ماذا تطلب من المورد | امنة (safe) | ثابتة الاثر (idempotent) |
|---|---|---|---|
| GET | جلب نسخة او تمثيل للمورد | نعم | نعم |
| HEAD | جلب ترويسات الاستجابة فقط دون الجسم | نعم | نعم |
| POST | معالجة البيانات المرفقة وفق قواعد المورد | لا | لا |
| PUT | استبدال المورد كاملا بالنسخة المرسلة | لا | نعم |
| PATCH | تطبيق تعديل جزئي على المورد | لا | لا |
| DELETE | ازالة المورد المستهدف من عنوانه | لا | نعم |
وتدرج المراجع والمواصفات الرسمية، مثل توثيق شبكة مطوري موزيلا (MDN Web Docs)، خاصية ثالثة بجانب الامان وثبات الاثر تبين مدى جواز تخزين استجابة الطريقة لاعادة استخدامها لاحقا، وتسمى قابلية التخزين المؤقت (cacheable). وتفرد هذه الدورة لمسالة التخزين المؤقت درسا مستقلا يشرح قواعدها وترويساتها بالتفصيل.
كما تعرف مواصفات بروتوكول HTTP طرقا قياسية اخرى تخدم حالات وظيفية متخصصة، وسنتناول كل طريقة منها في موضعها المناسب من موضوعات الدورة. ومن ابرز تلك الطرق طريقة الخيارات (OPTIONS)، التي تتيح للعميل الاستعلام عن القدرات والخيارات التي يدعمها الخادم للمورد دون طلب تنفيذ اجراء عليه، وكثيرا ما تلاحظها مسجلة في لوحة الشبكة حيث يرسلها المتصفح تلقائيا للتحقق من الصلاحيات قبل ارسال بعض الطلبات الموجهة الى خوادم اخرى.
لماذا يعيد العميل بعض الطلبات ويسألك قبل غيرها
يمثل ثبات الاثر الركيزة التقنية التي تمنح البرمجيات صلاحية تكرار الطلب تلقائيا دون الرجوع الى المستخدم، وهو الاجراء المعروف باسم اعادة المحاولة (retry). فاذا انقطع الاتصال بالشبكة قبل ان يستلم العميل رد الخادم، تسمح مواصفة HTTP للعميل بان يعيد ارسال طلبات GET او PUT او DELETE فورا وبصورة ذاتية؛ اذ يتيقن العميل من ان تكرار الطلب لن يضاعف التغيير او يفسد حالة المورد، حتى لو كان الطلب الاول قد وصل ونفذ بالفعل في الخادم قبل انقطاع الخط.
في المقابل، تحظر المواصفة القياسية على العميل اعادة ارسال الطلبات غير ثابتة الاثر — وعلى راسها POST — بصورة الية تلقائية، الا اذا توفرت للعميل الية موثقة يتاكد بها من ان الطلب الاول لم ينفذ اصلا او ان تكراره امن في ذلك السياق. وما لم تتوفر تلك الضمانة، تلزم المواصفة العميل بالتوقف واحالة القرار الى المستخدم البشري.
من هذا المنطلق المعياري ينشا مربع الحوار التحذيري الشهير الذي يظهره المتصفح عند تحديث بعض الصفحات. فاذا وصلت الى صفحة بعد ارسال نموذج عبر طلب POST، ثم حاولت اعادة تحميل تلك الصفحة، يجد المتصفح نفسه مضطرا لاعادة ارسال بيانات النموذج ذاتها مرة ثانية. ولما كان المتصفح يجهل ما اذا كانت هذه العملية ستؤدي الى تكرار خصم مالي او نشر تعليق مكرر او انشاء حساب اضافي، فانه يوقف الاجراء ويعرض تحذيرا صريحا يطلب موافقتك. ففي متصفح Google Chrome تظهر نافذة بعنوان تاكيد اعادة ارسال النموذج (Confirm Form Resubmission)، وفي متصفح Firefox تظهر رسالة تفيد بان عرض الصفحة يتطلب اعادة ارسال معلومات قد تكرر اجراء سابقا. اما الصفحة التي فتحتها بطلب GET، فيعيد المتصفح تحميلها فورا دون تردد او سؤال.
ويتضح المعنى التطبيقي لهذا السلوك في ممارستك اليومية: قبل ان توافق على اعادة ارسال النموذج، تامل طبيعة الاجراء الذي قمت به وما اذا كان تكراره مضرا. وحين يتاخر رد الخادم على طلب POST ارسلته، تذكر ان معاودة الضغط قد تنشئ اجراء مكررا، في حين تتيح لك طلبات GET وPUT وDELETE اعادة المحاولة بثقة تامة. وتوجد حلول معمارية تتيح تصميم خدمات تعالج طلبات POST بامان وتمنع تكرار اثارها، غير ان تفاصيل تلك الحلول ترتبط بمنظومة تصميم واجهات برمجة التطبيقات (APIs) التي نفرد لها درسا خاصا في نهاية الدورة.
من يتحمل أثر الطلب
تحدد طرق HTTP حدود المسؤولية القانونية والمعمارية بين طرفي الاتصال. فالعميل الذي يرسل طلب GET لا يتحمل اي تبعة لاي تعديل يطرا على الخادم نتيجة طلبه، لانه لم يطلب من الاساس سوى القراءة والاسترجاع. فاذا وظف متصفح تقنية الجلب المسبق وادى ذلك الى حذف تعليق، فان الخطا يقع كاملا على عاتق الموقع الذي خالف دلالة البروتوكول وربط اجراء الحذف بطريقة امنة.
وعلى النقيض من ذلك، يتحمل العميل الذي يرسل طلبات POST او PATCH المسؤولية الكاملة عن كل طلب يطلقه وما يترتب عليه من اثار؛ ولهذا تحجم البرمجيات عن اعادة ارسالها دون تدقيق وموافقة واعية. وفي المنتصف بين الطرفين تقف طريقتا PUT وDELETE؛ اذ تطلبان احداث تغيير فعلي على الخادم، لكن ثبات اثرهما يضمن ان تكرار الطلب لا يضاعف التغيير ولا يكدس الاثار.
وبفضل هذا التقسيم الدلالي المحكم، تكفي الكلمة الافتتاحية المفردة في سطر الطلب لتوجيه مختلف البرمجيات والانظمة عبر شبكة الانترنت العالمية؛ فمن خلالها تدرك الانظمة متى يحق لها التصرف التلقائي بسلام، ومتى يجب عليها التوقف وطلب اذن المستخدم.
اختبر فهمك
ثمانية اسئلة قصيرة تغطي افكار الدرس. اختر اجابة ثم اضغط «تحقق» لترى ان كانت صحيحة ولماذا. وفي اخر الاختبار تظهر نتيجتك، ومع كل سؤال اخطات فيه زر يعيدك الى القسم الذي يشرحه.
DELETE /comments/17 HTTP/1.1، ما الذي تحدده الكلمة DELETE؟/comments/17، ونتيجة المعالجة يذكرها رمز الحالة في الاستجابة.POST /articles/http-methods/comments بتعليق جديد، وأرسل تطبيق آخر طلب PUT /comments/40 بتعليق كامل. من حدد عنوان التعليق في كل طلب؟/comments/17 فيه حقلان: name وtext. أرسل العميل PUT /comments/17 وجسمه {"text":"Updated"} وحده. ماذا يطلب هذا الطلب بحسب معنى PUT؟UpdatedPUT /reports/5 بالرمز 405، ومعه الترويسة Allow: GET, HEAD. ماذا تفهم من هذه الاستجابة؟Allow تذكر الطرق التي يقبلها هذا المورد، وهي هنا GET وHEAD، فالرفض يخص هذا المورد لا الطريقة في كل مكان.GET /photos/8?action=delete، وقبله نافذة تسأل «هل أنت متأكد؟». ماذا قد يحدث حين يطلب برنامج جلب مسبق روابط الصفحة في متصفح صاحب الحساب؟DELETE /comments/17 مرتين. رد الخادم على الأول بالرمز 200، وعلى الثاني بالرمز 404. هل بقيت DELETE ثابتة الأثر؟POST /orders لتسجيل طلب شراء جديدPATCH /comments/17 بتغيير يضيف سطرا إلى آخر النصPUT /comments/17 بنسخة كاملة من التعليقPOST /messages لإرسال رسالة إلى مستخدم
