طرق 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.

جرّبها: فاحص طلبات HTTP جرّبها: مولّد أوامر cURL

الآمنة والمتكافئة: وعدان في RFC 9110

تكون الطريقة آمنة (Safe) حين يكون معناها للقراءة فقط: فالعميل لا يطلب تغييراً في حالة الخادم ولا يتوقعه. والطرق GET وHEAD وOPTIONS وTRACE آمنة. ويبقى مسموحاً للخادم أن يسجّل الطلب أو يعدّ مشاهدات الصفحة. ويضرب RFC 9110 مثلاً برابط مثل page?do=delete: إذا حذف اتباعُه بيانات، فالخلل في المورد لا في الزاحف الذي تبعه.

وتكون الطريقة متكافئة (Idempotent) حين يكون لإرسال الطلب نفسه عدة مرات الأثرُ المقصود نفسه على الخادم كما لو أُرسل مرة واحدة. فالطرق PUT وDELETE وكل الطرق الآمنة متكافئة، أما POST فليست كذلك، ولا PATCH في العموم. ضبط العنوان مرتين يترك عنواناً واحداً، أما «أضف عنصراً واحداً» مرتين فيضيف عنصرين. والتكافؤ يخص حالة الخادم لا الاستجابة: فقد تردّ عملية DELETE الثانية بالرمز 404 وتبقى صحيحة.

ويسمح RFC 9110 بتكرار الطلب المتكافئ تلقائياً إذا فشل الاتصال قبل وصول الاستجابة، وينص على أن العميل لا ينبغي أن يعيد تلقائياً طلباً غير متكافئ إلا إذا عرف أنه متكافئ فعلاً أو أنه لم يُطبَّق أصلاً. والآمن لا يعني المحمي: فطلب GET يحتاج إلى التفويض (Authorization) كغيره، ولا مكان للبيانات الحساسة في عنوانه، لأن الخوادم والوكلاء والمتصفحات تسجّله.

الطرق GET وHEAD وOPTIONS آمنة ومتكافئة، وPUT وDELETE تغيّران الحالة لكنهما متكافئتان، أما POST، وكذلك PATCH في العموم، فليستا آمنتين ولا متكافئتين، فلا ينبغي للعميل إعادة إرسالهما تلقائياً.
الطريقةآمنةمعناها القراءة فقطمتكافئةالتكرار = الأثر نفسهجسم الطلباستجابة النجاح المعتادة
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). ولا تختبر إلا أنظمة تملكها أو لديك إذن كتابي باختبارها.

جرّبها: منشئ طلبات API جرّبها: مرجع رموز حالة HTTP

مثال تطبيقي: نقطة نهاية واحدة وكل الطرق

واجهة دفتر عناوين توثّق 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

جرّبها: مختبِر REST API

أخطاء شائعة

  • فهم «آمنة» على أنها «محمية». فالآمنة تعني فقط أن العميل لا يطلب تغييراً، وطلب 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
الخطوات
  1. صنّف كل سطر في العقد: آمن أم لا، ومتكافئ أم لا.
  2. قارن كل ملاحظة بما تعد به طريقتها، واكتب السلوك المتوقع أو سؤالاً للفريق.
  3. رتّب العيوب حسب المخاطرة.
إظهار الإجابة النموذجية
الإجابة النموذجية

آمنتان ومتكافئتان بحكم طريقتهما: سطرا 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 SemanticsIETF · 2022معاني أساليب HTTP وحقول الترويسات ورموز الحالة والتفاوض على المحتوى، بغضّ النظر عن إصدار البروتوكول.
  • RFC 5789: PATCH Method for HTTPIETF · 2010أسلوب PATCH للتحديثات الجزئية، مقابل PUT الذي يستبدل المورد كاملاً.
  • HTTP request methods — MDNMDN Web Docs (Mozilla)طرق طلب HTTP (GET وPOST وPUT وPATCH وDELETE وغيرها)، وأيّها آمن وأيّها متساوي الأثر (idempotent) وأيّها قابل للتخزين المؤقت.
  • OWASP API Security Top 10 (2023)OWASP Foundation · 2023أكثر عشر نقاط ضعف شيوعاً في واجهات API: خلل التفويض على مستوى الكائن، وخلل التوثيق، والاستهلاك غير المقيد للموارد، وغيرها.

تدرّب بأدوات متقن

أنشئ طلبات HTTP وأرسلها (الطريقة وعنوان URL والترويسات والمصادقة والجسم) وافحص الاستجابة — بديل خفيف لـ Postman داخل متصفحك.

اختبار واجهات API

اختبر نقاط نهاية REST بتحكم كامل في الطريقة والترويسات وجسم JSON، ثم أضف تأكيدات على الحالة والترويسات ومسارات JSON.

اختبار واجهات API

إنشاء أوامر cURL من الطريقة وعنوان URL والترويسات والمتن وخيارات المصادقة.

الويب

اطّلع بالضبط على ما يرسله عميلك: الطريقة والترويسات والاستعلام والجسم وعنوان IP ومعلومات TLS.

اختبار واجهات API

ابحث عن أي رمز حالة HTTP لمعرفة معناه ومرجعه في RFC ومتى يُستخدم.

الويب

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة