أساسيات REST API
REST (Representational State Transfer) أسلوب معماري (Architectural Style) وصفه روي فيلدينغ (Roy Fielding) في أطروحته للدكتوراه عام 2000: مجموعة من القيود، لا بروتوكول ولا معيار. وواجهة REST تعرض موارد (Resources) — طلب شراء أو عميلاً أو مهمة — لكل منها معرّف URI. ويتعامل العملاء معها بطرق HTTP القياسية ويتبادلون تمثيلات (Representations) لها، غالباً بصيغة JSON.
مثال: واجهة لإدارة المهام تعرض المجموعة /tasks، ولكل مهمة عنوان URI خاص بها مثل /tasks/42. فالطلب GET /tasks/42 يعيد المهمة 42، وPATCH /tasks/42 مع {"done": true} يغيّر حقلاً واحداً، وDELETE /tasks/42 يحذفها. العنوان يسمّي الشيء، والطريقة تحدد ما يُفعل به، ورمز الحالة يخبرك بالنتيجة.
لماذا يهم
تتيح لك أعراف REST أن تتوقع السلوك الصحيح قبل أن ترسل أي طلب: الإنشاء يعيد 201 Created، والمورد المحذوف لا يعود موجوداً، والطريقة غير المدعومة تُرفض بالرمز 405. وحيثما خالفت الواجهة عرفاً دون توثيق، يُرجَّح أن يكتب مطورو العملاء شيفرة تتعامل معه بشكل خاطئ.
وتتضاعف كلفة عيب الواجهة بعدد عملائها. فحقل أُعيدت تسميته أو 500 لمدخلات سيئة قد يعطّل واجهة الويب الأمامية وتكامل أحد الشركاء وإصدارات التطبيق المثبتة على هواتف المستخدمين، مع أن أياً منها لم يتغير. ومعرفة الأعراف تحوّل ملاحظة «الواجهة تبدو غريبة» إلى توقعات دقيقة لحالات الاختبار.
الموارد وعناوين URI والتمثيلات وانعدام الحالة
يعرّف فيلدينغ REST بستة قيود، أحدها اختياري، منها انعدام الحالة (Stateless) والواجهة الموحّدة (Uniform Interface). وكثيراً ما تطبّقها الواجهات الموصوفة بأنها REST تطبيقاً جزئياً — فروابط الوسائط التشعبية (Hypermedia) التي تخبر العميل بما يمكنه فعله بعد ذلك تُترك غالباً — لذا احكم على الواجهة بعقدها أولاً، واستخدم أعراف REST لاكتشاف التناقضات. وأهم أربع أفكار للاختبار:
- المورد (Resource): شيء مسمّى تعرضه الواجهة — مهمة أو مستخدم أو قائمة المهام. الموارد أسماء، والفعل يأتي من الطريقة:
POST /tasksلاPOST /createTask. - عنوان URI: معرّف المورد، وصيغته معرّفة في RFC 3986. ومن الأعراف الشائعة مجموعة بصيغة الجمع
/tasks، وأعضاؤها/tasks/42، وموارد فرعية مثل/tasks/42/comments. - التمثيل (Representation): حالة المورد في صيغة محددة. يذكر العميل الصيغة التي يرسلها في
Content-Typeوالصيغ التي يستطيع قراءتها فيAccept. - انعدام الحالة (Statelessness): يحمل كل طلب كل ما يحتاجه الخادم لفهمه — بيانات الاعتماد مثل الرمز المميّز (Token)، والمعرّفات، ورقم الصفحة. ولا يحتفظ الخادم بسياق جلسة من الطلبات السابقة (أما الموارد المخزّنة نفسها فتبقى بالطبع)، فيمكن تكرار الطلب أو إرساله منفرداً أو معالجته على خادم آخر ويبقى معناه واحداً. واختبره على هذا الأساس: اطلب الصفحة 3 مباشرةً دون جلب الصفحتين 1 و2 أولاً.
ربط الطرق بعمليات CRUD
تشير CRUD إلى العمليات الأساسية على البيانات المخزنة: الإنشاء (Create) والقراءة (Read) والتحديث (Update) والحذف (Delete). وفي REST تمثّل كل عملية طريقةَ HTTP تُطبَّق على المجموعة أو على عنصر واحد. وقد تعرّفت إلى الطرق وإلى خاصيتَي كونها آمنة (Safe) ومتكافئة (Idempotent) في درس طرق HTTP؛ ويجمع الجدول بينها وبين الموارد.
والنمط وراء الجدول: تُنشئ على المجموعة، والخادم يختار عنوان URI للعنصر الجديد؛ وتقرأ المجموعة أو عنصراً واحداً؛ وتحدّث عنصراً واحداً أو تحذفه في عنوانه الخاص. أما التركيبات الخارجة عن الجدول — POST /tasks/42، أو PUT وPATCH وDELETE على المجموعة كلها — فلا تُتاح عادةً، ويجب أن تُقابَل بالرمز 405 Method Not Allowed.
| الطريقة | المورد | |
|---|---|---|
/tasksالمجموعة | /tasks/{id}عنصر واحد | |
GETالقراءة | عرض قائمة المهام200 OK، وغالباً مقسّمة إلى صفحات | قراءة مهمة واحدة200 OK · و404 إن لم تكن موجودة |
POSTالإنشاء | إنشاء مهمة؛ والخادم يختار المعرّف201 Created + Location | لا تُتاح عادةً405 + Allow |
PUTالتحديث: استبدال | لا تُتاح عادةً405 + Allow | استبدال المهمة كاملة200 أو 204 · و201 إن أنشأ المهمة |
PATCHالتحديث: بعض الحقول | لا تُتاح عادةً405 + Allow | تغيير الحقول المرسلة فقط200 أو 204 |
DELETEالحذف | لا تُتاح عادةً405 + Allow | حذف المهمة204 (أو 200 أو 202) · ثم يعيد GET الرمز 404 |
- عملية CRUD ورمز نجاحها المعتاد
- غير متاحة: توقّع
405 Method Not Allowedمع ترويسةAllow
تصميم معتاد: عقد الواجهة نفسها هو الذي يحدد التركيبات المتاحة.
النسخة النصية
Operation Method URI Typical success response
--------- ------ ----------- ---------------------------------------------
Create POST /tasks 201 Created + Location: /tasks/{id}
Read GET /tasks 200 OK, a list (often paged)
Read GET /tasks/{id} 200 OK, one task
Update PUT /tasks/{id} 200 OK or 204 No Content, whole task replaced
Update PATCH /tasks/{id} 200 OK or 204 No Content, sent fields only
Delete DELETE /tasks/{id} 204 No Content (200 with a body, 202 if queued)رموز الحالة في واجهة REST
يتفرّع سلوك العملاء بحسب رمز الحالة قبل قراءة الجسم، ولذلك فالرمز جزء من العقد. وفي REST ينتج الرمز عن العملية وعن حالة المورد، فتستطيع كل حالة اختبار أن تذكر الرمز المتوقع.
201 Createdبعد الإنشاء، مع ترويسةLocationتحمل عنوان المورد الجديد (RFC 9110). وإعادة200مع المعرّف في الجسم فقط انحراف شائع، والعقد هو الذي يحدد هل هو عيب.204 No Contentلتحديث أو حذف ناجح لا يعيد شيئاً: يجب أن يكون الجسم فارغاً.404 Not Foundلعنصر غير موجود، ومنه العنصر المحذوف للتو. أما القائمة الفارغة فهي200مع مصفوفة فارغة.405 Method Not Allowedلطريقة لا يدعمها المورد، مع ترويسةAllowتذكر الطرق التي يدعمها؛ وهذه الترويسة يشترطها RFC 9110.415 Unsupported Media Typeلجسم بصيغة لا يقبلها المورد؛ و406 Not Acceptableحين لا يستطيع الخادم إنتاج أيٍّ من الصيغ المذكورة فيAccept، مع أن RFC 9110 يسمح له أيضاً بإرسال صيغته الافتراضية بدلاً من ذلك.409 Conflictحين يتعارض الطلب مع الحالة الحالية، مثل بريد إلكتروني مسجّل مسبقاً؛ و400أو422للمدخلات غير الصالحة، باستخدام متسق.- لا
5xxأبداً لخطأ من العميل: فالرمز500لمدخلات سيئة يعني غالباً أن التحقق من صحة المدخلات أو معالجة الأخطاء مفقودة.
مثال تطبيقي: مهمة واحدة عبر دورة حياتها
يمرّر المختبِر مهمة واحدة عبر كل العمليات، ويتحقق بعد كل خطوة من رمز الحالة ومن الحالة المخزنة. ويبدأ حساب الاختبار دون أي مهام.
- تستخدم الخطوات اللاحقة
/v1/tasks/57المأخوذ من ترويسةLocationبدلاً من عنوان مخمَّن. - الطريقة POST تخص المجموعة: فعلى العنصر
/v1/tasks/57تُقابَل بالرمز405، وتذكر ترويسةAllowالطرق التي يدعمها العنصر فعلاً. - بعد الحذف يختفي العنصر، فيعيد
GET /v1/tasks/57الرمز404؛ أما المجموعة فما زالت موجودة، فيعيدGET /v1/tasksالرمز200مع مصفوفة فارغة، لا404. - وتبقى لكل طريقة وعودها الخاصة هنا أيضاً — فـPATCH يغيّر الحقول المرسلة فقط، وPUT يحمل الحالة الكاملة، وطلب DELETE المكرر قد يعيد
404ويبقى متكافئاً — كما يشرح قسما الطرق الآمنة والمتكافئة وما تختبره في كل طريقة في درس طرق HTTP.
POST /v1/tasks {"title": "Pay rent", "done": false}
-> 201 Created, Location: /v1/tasks/57
GET /v1/tasks/57
-> 200 OK, {"id": 57, "title": "Pay rent", "done": false}
PATCH /v1/tasks/57 {"done": true}
-> 200 OK, {"id": 57, "title": "Pay rent", "done": true}
POST /v1/tasks/57
-> 405 Method Not Allowed, Allow: GET, HEAD, PUT, PATCH, DELETE
DELETE /v1/tasks/57
-> 204 No Content
GET /v1/tasks/57
-> 404 Not Found
GET /v1/tasks
-> 200 OK, []إدارة الإصدارات والتغييرات الكاسرة
للواجهة عملاء لا يتحكم فيهم فريقها، فلا يستطيع تغييرها بحرية. والتغيير الكاسر (Breaking Change) هو ما يجعل عميلاً سليماً لم يتغير يتعطّل: حذف حقل أو إعادة تسميته، أو تغيير نوعه، أو جعل حقل اختياري في الطلب إلزامياً، أو تغيير عنوان URI أو رمز حالة. أما إضافة نقطة نهاية أو حقل اختياري فآمنة عادةً، بشرط أن يتجاهل العملاء الحقول التي لا يعرفونها.
لا يفرض REST نظاماً لإدارة الإصدارات (Versioning). تختار الفرق نظاماً وتوثّقه في العقد، وغالباً ما يكون مستند OpenAPI: مسار URI (/v1/tasks)، أو معامل استعلام (?version=2)، أو ترويسة طلب مخصصة مثل Api-Version: 2 (ويختلف اسمها من واجهة لأخرى)، أو نوع الوسائط (Accept: application/vnd.example.v2+json).
- بعد إطلاق نسخة جديدة، شغّل اختبارات الانحدار للنسخة القديمة دون تعديل: يجب أن تبقى
v1تتصرف كما ينص عقدها. - أرسل الطلب نفسه إلى النسختين، وتأكد من أن الفروق الظاهرة هي الفروق الموثّقة فقط.
- أرسل طلباً بلا نسخة، وبنسخة مجهولة، وبنسخة أُوقف العمل بها: توقّع السلوك الافتراضي الموثّق أو خطأ
4xxواضحاً، لا500أبداً.
أخطاء شائعة
- التعامل مع REST كمعيار بقواعد ثابتة. إنه أسلوب معماري، وعقد الواجهة هو الذي يحدد التفاصيل.
- اختبار الطلبات بالترتيب الذي ترسلها به واجهة المستخدم فقط. فطلب REST عديم الحالة، لذا أرسله منفرداً أيضاً: الصفحة 3 دون الصفحتين 1 و2، والعنصر بعنوانه دون تحميل القائمة.
- قبول أي
2xxنجاحاً مع أن العملاء يعتمدون على الرمز الدقيق، مثل201معLocation. - توقّع
404لقائمة فارغة. فالمجموعة ما زالت موجودة، والإجابة الصحيحة200مع مصفوفة فارغة؛ أما404فللعنصر غير الموجود. - اختبار أحدث نسخة فقط بعد الإصدار، وتفويت تغيير تسرّب إلى
v1.
من منظور ضمان الجودة
تظهر قيمة معرفة REST قبل تشغيل أي شيفرة. راجع العقد الجديد أو المعدّل كما تراجع المتطلبات: لكل مورد، ما الطرق المتاحة، وما رمز الحالة لكل منها، وماذا يحدث عند التكرار أو غياب العنصر، وهل التغيير كاسر. واتفق على الإجابات مع المطورين ومع الفرق التي تستهلك الواجهة — الويب والجوال والشركاء.
اكتب رمز الحالة المتوقع وأهم الترويسات في كل حالة اختبار، واحتفظ باختبار دورة حياة واحد لكل مورد. وفي تقرير الخطأ اذكر الطريقة وعنوان URI وجسم الطلب ورمز الحالة المتوقع والفعلي، ليعيد المطور تنفيذ الطلب في ثوانٍ.
تمرين عملي
راجع سجل واجهة حجز مواعيد في عيادة
تختبر مورد المواعيد في واجهة لحجز مواعيد عيادة على بيئة Staging. يعرّف العقد /v1/appointments و/v1/appointments/{id}، ويوثّق 201 Created مع ترويسة Location عند الإنشاء وتصفية القائمة بالمعامل date، ويعيد 404 للعناصر غير الموجودة. قرّر، سطراً سطراً، هل كل استجابة مرصودة صحيحة؛ ولكل استجابة خاطئة اذكر الاستجابة المتوقعة وسببها.
# Request Observed response
1 POST /v1/appointments (valid JSON body) 200 OK, body has "id": 381,
no Location header
2 GET /v1/appointments?date=2026-11-02 404 Not Found,
no appointments on that date
3 POST /v1/appointments/381 404 Not Found
4 POST /v1/appointments Content-Type: text/plain 500 Internal Server Error
5 DELETE /v1/appointments/381 204 No Content
6 GET /v1/appointments/381 404 Not Found
7 DELETE /v1/appointments/381 500 Internal Server Error
8 GET /v1/appointments/377 (after v2 release) "time" is now named "startsAt"- اكتب رمز الحالة المتوقع (والترويسة حين تهم) انطلاقاً من الطريقة وعنوان URI وحالة المورد في تلك اللحظة.
- قارنه بالاستجابة المرصودة، وصنّف السطر: ناجح أو عيب.
- رتّب العيوب بحسب أثرها على العملاء والمستخدمين.
إظهار الإجابة النموذجية
الصحيح: السطران 5 و6. فبعد الحذف يكون 404 هو المطلوب تماماً.
السطر 1: المتوقع 201 Created مع Location: /v1/appointments/381 كما يوثّق العقد. والعملاء الذين يقرؤون العنوان الجديد من Location لا يستطيعون المتابعة.
السطر 2: المجموعة موجودة حتى إن لم يطابق أي موعد المرشِّح (Filter)، فالمتوقع 200 OK مع مصفوفة فارغة. أما 404 فيخبر العملاء بأن القائمة نفسها غير موجودة، وكثير منهم سيعرض رسالة خطأ بدلاً من يوم بلا مواعيد.
السطر 3: الطريقة POST تخص المجموعة /v1/appointments لا العنصر، والموعد 381 موجود، فالرمز 404 مضلّل؛ والمتوقع 405 Method Not Allowed مع ترويسة Allow تذكر الطرق التي يدعمها العنصر.
السطر 4: صيغة الجسم غير المدعومة خطأ من العميل؛ والمتوقع 415 Unsupported Media Type لا انهيار الخادم.
السطر 7: الموعد محذوف مسبقاً، فالمتوقع 404 كما ينص العقد للعناصر غير الموجودة. و500 حالة غير معالَجة؛ تأكد بطلب GET أن الحالة لم تتغير.
السطر 8: تغيير كاسر تسرّب إلى v1. فإعادة التسمية مكانها v2 وحدها.
أبلغ أولاً عن السطر 8 (يعطّل العملاء الحاليين)؛ ثم السطرين 4 و7 (500 حيث يُتوقع 4xx)؛ ثم الأسطر 1 و2 و3 (رموز مضلّلة).
أسئلة شائعة
هل REST هو HTTP نفسه؟
لا. HTTP بروتوكول تعرّفه معايير IETF مثل RFC 9110، أما REST فأسلوب معماري. تعمل واجهات REST عادةً فوق HTTP، لكن واجهة HTTP قد تتجاهل REST كلياً، كأن ترسل كل إجراء بطلب POST إلى عنوان واحد.
هل يعيد الإنشاء 200 أم 201؟
ينص RFC 9110 على أنه حين ينشئ POST مورداً، ينبغي أن يرسل الخادم 201 Created مع ترويسة Location تحدّد المورد. وبعض الواجهات تعيد 200 مع المعرّف الجديد في الجسم؛ وهذا يعمل فقط إن نص عليه العقد وتوقعه كل العملاء. اختبر وفق العقد، وأبلغ عن ذلك حين تختلف نقاط نهاية الواجهة نفسها في ذلك.
كيف تقسّم واجهة REST قائمة طويلة إلى صفحات (Pagination)؟
لا يفرض REST نظاماً لذلك، فيجب أن يحدده العقد. ومن التصاميم الشائعة معاملات رقم الصفحة أو الإزاحة (Offset) مثل ?page=3&size=20، ومؤشر (Cursor) مُعتم تعيده كل استجابة لاستخدامه في الطلب التالي؛ وبعض الواجهات تعيد أيضاً عنوان URI للصفحة التالية، في الجسم أو في ترويسة Link. اختبر الصفحة الأولى والأخيرة، وصفحة بعد النهاية (200 مع مصفوفة فارغة، أو خطأ 4xx الموثّق)، وأكبر حجم صفحة مسموح وما يزيد عليه بواحد، وتأكد من أن أي عنصر لا يُتخطّى ولا يتكرر حين تُضاف عناصر بين الطلبات، وهو ضعف معروف في الترقيم بالإزاحة.
أي نظام لإدارة الإصدارات هو الأفضل؟
لا توجد إجابة معيارية. وضع النسخة في مسار URI سهل الرؤية والتوجيه والاختبار، وإدارة الإصدارات بالترويسة أو بنوع الوسائط تُبقي عناوين URI ثابتة. والمهم للاختبار أن يكون النظام موثّقاً، ومطبّقاً بالطريقة نفسها على كل نقاط النهاية، وأن تبقى النسخ القديمة تعمل حتى موعد إيقافها المعلن.
المراجع
- RFC 9110: HTTP Semanticsمعاني أساليب HTTP وحقول الترويسات ورموز الحالة والتفاوض على المحتوى، بغضّ النظر عن إصدار البروتوكول.
- RFC 3986: Uniform Resource Identifier (URI): Generic Syntaxأجزاء URI (النظام والسلطة والمسار والاستعلام والجزء) والمحارف المحجوزة والترميز بالنسبة المئوية.
- RFC 5789: PATCH Method for HTTPأسلوب PATCH للتحديثات الجزئية، مقابل PUT الذي يستبدل المورد كاملاً.
- OpenAPI Specificationالمعيار لوصف واجهات REST: المسارات والعمليات والمعاملات والمخططات والاستجابات وأنظمة الأمان.
تدرّب بأدوات متقن
اختبر نقاط نهاية REST بتحكم كامل في الطريقة والترويسات وجسم JSON، ثم أضف تأكيدات على الحالة والترويسات ومسارات JSON.
أنشئ طلبات HTTP وأرسلها (الطريقة وعنوان URL والترويسات والمصادقة والجسم) وافحص الاستجابة — بديل خفيف لـ Postman داخل متصفحك.
تحليل رمز حالة HTTP وترويسات الاستجابة، مع شرح يبيّن ما إذا كان الرمز صحيحاً في هذا الموقف.
ابحث عن أي رمز حالة HTTP لمعرفة معناه ومرجعه في RFC ومتى يُستخدم.
قارن استجابتي API (مثل بيئة التجريب مقابل الإنتاج) واحصل على قائمة بكل فرق بنيوي أو في القيم.
عرض مواصفة OpenAPI 3.x / Swagger 2.0 (بصيغة JSON أو YAML) كتوثيق قابل للتصفح لنقاط النهاية.
للتعمّق أكثر
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.