طرق HTTP
طريقة HTTP (Method) هي الكلمة الأولى في سطر كل طلب، وتخبر الخادم بما يريده العميل من المورد المستهدف (Resource)، أي الشيء الذي يحدده العنوان (URI)، مثل طلبية. فالطلب GET /orders/42 يطلب الطلبية رقم 42، أما DELETE /orders/42 فيطلب من الخادم حذفها. العنوان واحد، لكن المعنى والاستجابة المتوقعة والمخاطرة مختلفة تماماً.
يعرّف المعيار RFC 9110 الخاص بدلالات HTTP (HTTP Semantics) الطرقَ GET وHEAD وPOST وPUT وDELETE وCONNECT وOPTIONS وTRACE، ويضيف RFC 5789 الطريقة PATCH. ولكل طريقة معنى محدد وخاصيتان يعتمد عليهما المختبِر: هل هي آمنة (Safe)، وهل هي متكافئة (Idempotent). ويتناول هذا الدرس الطرق السبع التي تستخدمها تطبيقات الويب والواجهات البرمجية (APIs) كل يوم.
لماذا يهم
الطريقة وعدٌ لكل برنامج يقف بين المستخدم والخادم. فزواحف محركات البحث وخدمات معاينة الروابط تتبع روابط GET، والمتصفحات تجلب الصفحات مسبقاً، وعملاء HTTP قد يعيدون إرسال الطلب المتكافئ تلقائياً إذا انقطع الاتصال. وهذا بلا ضرر ما دام التطبيق يفي بالوعد: فقد يشغّل زاحفٌ إجراءَ حذف وُضع خلف رابط GET.
وبالنسبة إلى المختبِر، تتحول الطرق إلى قائمة جاهزة من التوقعات لكل نقطة نهاية (Endpoint): ما الذي يجب ألا يغيّر الحالة، وما الذي يجوز إرساله مرتين، وأي الطرق يجب رفضها. وكثيراً ما تُكتشف الطلبيات المكررة والتحديثات التي تمسح حقولاً والمستخدمون العاديون القادرون على حذف السجلات بتغيير الطريقة وحدها أو بإرسال الطلب نفسه مرتين.
الطرق السبع التي ستختبرها
الاستجابات أدناه هي المعتادة، وعقد الواجهة يحدد الرموز بدقة. ويعرّف RFC 9110 أيضاً CONNECT (نفق عبر وكيل) وTRACE (إعادة الطلب كما وصل لأغراض التشخيص)، ونادراً ما تُختبران داخل التطبيق. وأسماء الطرق حساسة لحالة الأحرف، والقياسية منها تُكتب بأحرف كبيرة.
GETتجلب تمثيلاً (Representation) للمورد، أي حالته الحالية بصيغة مثل JSON أو HTML، وتردّ عادةً بالرمز200 OK. والمحتوى المرسل في طلب GET ليس له معنى محدد في RFC 9110، وبعض الخوادم ترفضه.HEADهي GET بلا جسم في الاستجابة. وينبغي أن يرسل الخادم الترويسات نفسها التي يرسلها مع GET، فيستطيع العميل التأكد من وجود المورد أو حجمه أو نوعه دون تنزيله. وكل خادم عام الغرض ملزم بدعم GET وHEAD.POSTترسل محتوى ليعالجه المورد وفق قواعده الخاصة: إنشاء طلبية في/orders، أو إرسال نموذج، أو بدء إجراء مثل/orders/42/cancel. وإذا أنشأت شيئاً فالمتوقع201 Createdمع ترويسةLocation.PUTتنشئ المورد أو تستبدله بالحالة الكاملة الموجودة في الجسم:200أو204عند الاستبدال، و201عند الإنشاء.PATCH(وفق RFC 5789) تطبّق التغييرات الموصوفة في مستند تعديل (Patch Document)، فلا يتغير إلا ما يذكره المستند. وتحدد ترويسةContent-Typeصيغته، مثلapplication/merge-patch+json.DELETEتحذف المورد، وتردّ عادةً بالرمز204 No Content، أو200مع رسالة، أو202 Acceptedإذا وُضع الحذف في قائمة انتظار. وكما في GET، ليس للمحتوى المرسل في طلب DELETE معنى محدد.OPTIONSتسأل عن الطرق والميزات التي يدعمها المورد، والجواب في ترويسات مثلAllow. وترسلها المتصفحات أيضاً من تلقاء نفسها طلباً تمهيدياً (Preflight) في CORS، وهو ما يشرحه درس CORS.
الآمنة والمتكافئة: وعدان في RFC 9110
تكون الطريقة آمنة (Safe) حين يكون معناها للقراءة فقط: فالعميل لا يطلب تغييراً في حالة الخادم ولا يتوقعه. والطرق GET وHEAD وOPTIONS وTRACE آمنة. ويبقى مسموحاً للخادم أن يسجّل الطلب أو يعدّ مشاهدات الصفحة. ويضرب RFC 9110 مثلاً برابط مثل page?do=delete: إذا حذف اتباعُه بيانات، فالخلل في المورد لا في الزاحف الذي تبعه.
وتكون الطريقة متكافئة (Idempotent) حين يكون لإرسال الطلب نفسه عدة مرات الأثرُ المقصود نفسه على الخادم كما لو أُرسل مرة واحدة. فالطرق PUT وDELETE وكل الطرق الآمنة متكافئة، أما POST فليست كذلك، ولا PATCH في العموم. ضبط العنوان مرتين يترك عنواناً واحداً، أما «أضف عنصراً واحداً» مرتين فيضيف عنصرين. والتكافؤ يخص حالة الخادم لا الاستجابة: فقد تردّ عملية DELETE الثانية بالرمز 404 وتبقى صحيحة.
ويسمح RFC 9110 بتكرار الطلب المتكافئ تلقائياً إذا فشل الاتصال قبل وصول الاستجابة، وينص على أن العميل لا ينبغي أن يعيد تلقائياً طلباً غير متكافئ إلا إذا عرف أنه متكافئ فعلاً أو أنه لم يُطبَّق أصلاً. والآمن لا يعني المحمي: فطلب GET يحتاج إلى التفويض (Authorization) كغيره، ولا مكان للبيانات الحساسة في عنوانه، لأن الخوادم والوكلاء والمتصفحات تسجّله.
| الطريقة | آمنةمعناها القراءة فقط | متكافئةالتكرار = الأثر نفسه | جسم الطلب | استجابة النجاح المعتادة |
|---|---|---|---|---|
GETالقراءة | نعم | نعم | بلا معنى محدد | 200 OKمع التمثيل |
HEADالترويسات فقط | نعم | نعم | بلا معنى محدد | 200 OKترويسات GET نفسها بلا جسم |
OPTIONSما المدعوم | نعم | نعم | بلا استخدام محدد | 200 أو 204مع Allow |
PUTإنشاء أو استبدال | لا | نعم | الحالة الجديدة الكاملة | 200 أو 204201 إذا أنشأ المورد |
DELETEالحذف | لا | نعم | بلا معنى محدد | 204 أو 200 أو 202202 إذا وُضع في قائمة انتظار |
POSTمعالجة المحتوى | لا | لا | محتوى للمعالجة | 201 Createdمع Location عند الإنشاء |
PATCHتغيير جزئي | لا | ليست في العمومقد يكون تعديل بعينه متكافئاً | مستند تعديل | 200 أو 204 |
الخصائص كما يعرّفها RFC 9110، وPATCH كما يعرّفها RFC 5789. ورموز الحالة هي المعتادة، وعقد الواجهة يحدد الرموز بدقة.
النسخة النصية
Method Safe Idempotent Request body Typical success response
------- ---- -------------- ------------------- -------------------------------
GET yes yes no defined meaning 200 + the representation
HEAD yes yes no defined meaning 200, same headers as GET, no body
OPTIONS yes yes no defined use 200 or 204 + Allow
PUT no yes full new state 200 or 204; 201 if it created
DELETE no yes no defined meaning 204, 200, or 202 if queued
POST no no content to process 201 + Location if it created
PATCH no not in general patch document 200 or 204ما الذي تختبره في كل طريقة
حوّل كل وعد إلى شروط اختبار (Test Conditions). وبعد كل طلب افحص أمرين: الاستجابة، وحالة المورد التي تقرؤها بطلب GET منفصل أو من قاعدة البيانات.
- GET وHEAD: لا شيء يتغير مهما أرسلتهما. وتردّ HEAD برمز الحالة والترويسات نفسها التي تردّ بها GET مع جسم فارغ. وابحث عن إجراءات مخبأة في روابط GET مثل
?action=cancel. - POST: أرسل الطلب نفسه مرتين كما يحدث عند النقر المزدوج أو إعادة المحاولة، واختبر قاعدة التكرار المتفق عليها مع الفريق: الرفض أو الدمج أو القبول. وبعض الواجهات تقبل مفتاحاً يولّده العميل، غالباً في ترويسة
Idempotency-Key، لتتعرف على الطلب المكرر. - PUT: أرسلها مرتين وتوقّع حالة مخزنة واحدة. واحذف حقلاً اختيارياً من الجسم: توقّع أن يُمسح الحقل أو أن يُرفض الطلب كما ينص العقد؛ فالاحتفاظ بالقيمة القديمة بصمت يعني أن PUT تُطبَّق كأنها تحديث جزئي.
- PATCH: قارن المورد كاملاً قبل الطلب وبعده؛ فالحقول التي لم ترسلها يجب ألا تتغير. والصيغة غير المدعومة لمستند التعديل يجب أن تُرفض بالرمز
415 Unsupported Media Typeمع ترويسةAccept-Patchكما يوصي RFC 5789. - DELETE: طلب GET بعدها يردّ بالرمز
404، وتكرار DELETE لا يغيّر شيئاً آخر، والبيانات المرتبطة تُعالج كما ينص المتطلب. - الطرق غير المدعومة: توقّع
405 Method Not Allowedمع ترويسةAllowالتي يجعلها RFC 9110 إلزامية، أو501 Not Implementedلطريقة لا يعرفها الخادم أصلاً. والرد بالرمز200أو500عيب، ويجب أن تذكر OPTIONS الطرق التي تعمل فعلاً. - التفويض لكل طريقة: المستخدم المسموح له بقراءة سجل بطريقة GET ليس بالضرورة مسموحاً له بتعديله بطريقة PUT أو حذفه بطريقة DELETE. كرّر طرق الكتابة بحساب أقل صلاحية؛ وتسمي قائمة OWASP API Security Top 10 (2023) هذا الخطر التفويض المعطوب على مستوى الوظيفة (Broken Function Level Authorization). ولا تختبر إلا أنظمة تملكها أو لديك إذن كتابي باختبارها.
مثال تطبيقي: نقطة نهاية واحدة وكل الطرق
واجهة دفتر عناوين توثّق GET وHEAD وOPTIONS وPUT وPATCH وDELETE على /v1/addresses/{id}، والعنوان رقم 7 يخص المستخدم A. وبدلاً من حالة اختبار واحدة غامضة باسم «تحديث العنوان»، يكتب المختبِر صفاً لكل وعد، ويفحص في كل صف الحالة المخزنة إلى جانب رمز الحالة:
- الصف 4 يميّز PUT من PATCH: فالاحتفاظ بالمدينة القديمة يعني أن PUT تُطبَّق كأنها تحديث جزئي.
- الصف 8 يُنفَّذ والعنوان 7 ما زال موجوداً؛ والرد بالرمز
204فيه يعني أن المستخدم B يستطيع حذف بيانات مستخدم آخر، وهذا عيب تفويض حرج.
# Request (as user A unless stated) Expected result
1 GET /v1/addresses/7, sent twice 200 both times, same body, nothing changed
2 HEAD /v1/addresses/7 200, same headers as GET, empty body
3 PUT /v1/addresses/7 (full body), twice 200 or 204 both times, one stored address
4 PUT /v1/addresses/7 without "city" 4xx (city is required), address unchanged
5 PATCH /v1/addresses/7 {"zip": "12271"} 200, only zip changed; street and city kept
6 POST /v1/addresses/7 405 + Allow: GET, HEAD, OPTIONS, PUT, PATCH,
DELETE
7 OPTIONS /v1/addresses/7 200 or 204, Allow lists the same six methods
8 DELETE /v1/addresses/7 as user B 403 or 404, address 7 still exists
9 DELETE /v1/addresses/7 204, then GET returns 404
10 DELETE /v1/addresses/7 again 404 as documented, no other address affectedأخطاء شائعة
- فهم «آمنة» على أنها «محمية». فالآمنة تعني فقط أن العميل لا يطلب تغييراً، وطلب GET يحتاج إلى المصادقة والتفويض كغيره.
- إرسال كل طلب POST مرة واحدة فقط. فالإرسال المزدوج وإعادة المحاولة مصدر شائع للطلبيات والمدفوعات المكررة.
- توقّع استجابات متطابقة من طريقة متكافئة. فتكرار DELETE قد يردّ بالرمز
404؛ والتكافؤ يخص الحالة على الخادم. - معاملة PUT وPATCH كأنهما قابلتان للتبادل، وعدم فحص الحقول التي لم تُرسَل.
- اختبار الطرق التي تستدعيها واجهة المستخدم فقط. فأي عميل يستطيع إرسال أي طريقة، لذا تأكد أن الطرق غير المدرجة تُرفض بالرمز
405معAllow.
من منظور ضمان الجودة
الطرق قائمة مراجعة قبل كتابة أي شيفرة. لكل نقطة نهاية في قصة مستخدم أو عقد واجهة، اكتب طرقها واسأل: ما الذي يتغير على الخادم؟ هل يجوز تكرار الطلب؟ وماذا يحدث عند التكرار؟ واسأل مطوري الويب والجوال هل يعيد عملاؤهم المحاولة بعد انتهاء المهلة؛ ففي شبكات الجوال تُعدّ إعادة إرسال POST سيناريو حقيقياً.
اذكر الطريقة في كل حالة اختبار وكل تقرير عيب: فعبارة «تحديث العنوان» قد تعني PUT أو PATCH، والطلب بلا طريقته لا يمكن إعادة تنفيذه. وللنقاط التي لها أدوار، احتفظ بجدول صغير للطرق مقابل الأدوار يذكر رمز الحالة المتوقع في كل خلية، وأعد تشغيله كلما تغيرت الصلاحيات.
تمرين عملي
راجع طرق واجهة سلة متجر
تختبر واجهة متجر على بيئة Staging. استناداً إلى مقتطف العقد والملاحظات الست أدناه، حدّد هل كل طريقة موثقة آمنة وهل هي متكافئة، ثم قرّر لكل ملاحظة هل هي عيب، وما الذي كان يجب أن يحدث، ولماذا.
Contract excerpt
GET /v1/cart read the cart
POST /v1/cart/items add an item, body {"sku": "A1", "qty": 1}
PUT /v1/cart/items/{sku} set the quantity of an item, body {"qty": 2}
DELETE /v1/cart/items/{sku} remove an item
PATCH /v1/profile change some profile fields
GET /v1/coupons/apply?code=X apply a coupon to the cart
Observations
a PUT /v1/cart/items/A1 {"qty": 2}, sent twice -> quantity is 4
b Opening /v1/coupons/apply?code=SAVE10 twice -> discount applied twice
c HEAD /v1/cart -> 200 with the full JSON body
d DELETE /v1/cart (not in the contract) -> 500 Internal Server Error
e PATCH /v1/profile {"phone": "0550000000"} -> 200, "email" is now null
f POST /v1/cart/items, retried after a timeout -> the same item appears twice- صنّف كل سطر في العقد: آمن أم لا، ومتكافئ أم لا.
- قارن كل ملاحظة بما تعد به طريقتها، واكتب السلوك المتوقع أو سؤالاً للفريق.
- رتّب العيوب حسب المخاطرة.
إظهار الإجابة النموذجية
آمنتان ومتكافئتان بحكم طريقتهما: سطرا GET، مع أن سطر القسيمة يصف تغييراً في الحالة (انظر الملاحظة b). متكافئتان وغير آمنتين: PUT وDELETE. لا آمنة ولا متكافئة: POST، وكذلك PATCH في العموم.
الملاحظة a: عيب. PUT تضبط الحالة، فطلبان متطابقان يجب أن يتركا الكمية 2؛ أما هذا الخادم فيضيف بدلاً من ذلك.
الملاحظة b: عيب في التصميم. تطبيق القسيمة يغيّر الحالة، فلا يجوز وضعه خلف GET حيث قد تشغّله الزواحف ومعاينات الروابط والجلب المسبق. المتوقع: طريقة غير آمنة مثل POST /v1/cart/coupons. وحتى عندئذ، يجب ألا يضاعف تطبيقُ الرمز نفسه مرتين الخصمَ إلا إذا سمحت قواعد القسيمة بذلك.
الملاحظة c: عيب. استجابة HEAD يجب ألا تحتوي جسماً، وينبغي أن تطابق ترويساتها ترويسات GET.
الملاحظة d: عيب. المتوقع 405 Method Not Allowed مع ترويسة Allow تذكر الطرق المدعومة، لا خطأ في الخادم.
الملاحظة e: عيب. يجب ألا تغيّر PATCH إلا الحقول المرسلة؛ ومسح البريد الإلكتروني فقدان للبيانات، وقد يمنع المستخدم من دخول حسابه.
الملاحظة f: ليست عيباً بالضرورة، لأن POST ليست متكافئة. اسأل هل ينبغي للعميل أن يعيد محاولة POST أصلاً، وهل إضافة SKU موجود يجب أن تدمج الكميات، ثم اختبر القاعدة المتفق عليها.
ترتيب المخاطرة: e (فقدان البيانات)، ثم b (خصومات تشغّلها أدوات آلية)، ثم a (كميات وإجماليات خاطئة)، ثم d وc؛ وتبقى f مفتوحة حتى يجيب الفريق.
أسئلة شائعة
ما الفرق بين PUT وPATCH؟
ترسل PUT الحالة الجديدة الكاملة للمورد فتستبدل الموجود أو تنشئه. أما PATCH فترسل وصفاً للتغييرات فقط، مثل قيمة جديدة لحقل واحد. وإرسال طلب PUT نفسه مرتين يترك دائماً الحالة نفسها، أما PATCH فليست متكافئة في العموم، لأن تغييراً مثل «أضف 1 إلى الكمية» يتراكم.
هل يمكن أن يحمل طلب GET جسماً؟
صياغة الرسالة في HTTP تسمح بذلك، لكن RFC 9110 ينص على أن المحتوى في طلب GET ليس له معنى محدد عموماً، ولا يغيّر معنى الطلب، وقد يجعل بعض الخوادم ترفض الطلب. ضع مدخلات GET في العنوان كما يشرح الدرس التالي عن معاملات المسار والاستعلام، أو استخدم POST حين يحتاج البحث إلى جسم كبير منظم.
هل POST للإنشاء فقط؟
لا. تطلب POST من المورد معالجة المحتوى وفق قواعده: إنشاء عنصر، أو إرسال نموذج، أو بدء مهمة، أو تنفيذ بحث معقد. ولا يُتوقع 201 Created مع Location إلا حين تُنشئ مورداً؛ وفي غير ذلك 200 أو 202 أو 204 كما يوثّق العقد.
لماذا أرى في أدوات المطور (DevTools) طلبات OPTIONS لم يكتبها أحد؟
ترسلها المتصفحات طلباتٍ تمهيدية (Preflight) في CORS: فقبل بعض الطلبات بين مصادر مختلفة، مثل PUT أو DELETE أو طلب بترويسات مخصصة، يسأل المتصفح الخادم هل الطلب الحقيقي مسموح. وإذا فشل الطلب التمهيدي فلن يُرسَل الطلب الحقيقي أبداً. ويشرح درس CORS ذلك بالتفصيل.
المراجع
- RFC 9110: HTTP Semanticsمعاني أساليب HTTP وحقول الترويسات ورموز الحالة والتفاوض على المحتوى، بغضّ النظر عن إصدار البروتوكول.
- RFC 5789: PATCH Method for HTTPأسلوب PATCH للتحديثات الجزئية، مقابل PUT الذي يستبدل المورد كاملاً.
- HTTP request methods — MDNطرق طلب HTTP (GET وPOST وPUT وPATCH وDELETE وغيرها)، وأيّها آمن وأيّها متساوي الأثر (idempotent) وأيّها قابل للتخزين المؤقت.
- OWASP API Security Top 10 (2023)أكثر عشر نقاط ضعف شيوعاً في واجهات API: خلل التفويض على مستوى الكائن، وخلل التوثيق، والاستهلاك غير المقيد للموارد، وغيرها.
تدرّب بأدوات متقن
أنشئ طلبات HTTP وأرسلها (الطريقة وعنوان URL والترويسات والمصادقة والجسم) وافحص الاستجابة — بديل خفيف لـ Postman داخل متصفحك.
اختبر نقاط نهاية REST بتحكم كامل في الطريقة والترويسات وجسم JSON، ثم أضف تأكيدات على الحالة والترويسات ومسارات JSON.
إنشاء أوامر cURL من الطريقة وعنوان URL والترويسات والمتن وخيارات المصادقة.
اطّلع بالضبط على ما يرسله عميلك: الطريقة والترويسات والاستعلام والجسم وعنوان IP ومعلومات TLS.
ابحث عن أي رمز حالة HTTP لمعرفة معناه ومرجعه في RFC ومتى يُستخدم.
للتعمّق أكثر
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.