شرح صفوف ومحتوى الفقرة
يخضع بروتوكول HTTP في إصداره النصي لقواعد نحوية صارمة لا تقبل التسامح في مواضع المسافات والفواصل. فمجرد مسافة في غير موضعها أو شرطة مائلة مفقودة أو سطر فارغ منسي كفيل بجعل الخادم يرفض الرسالة فوراً برمز خطأ العميل 400 Bad Request أو بتعليق الاتصال. وتتركز أبرز الأخطاء الشائعة في صياغة سطر البداية (Start-Line) وحقول الرؤوس في النقاط التالية:
- أخطاء مسار الهدف: تُفصل عناصر سطر الطلب الثلاثة بمسافة قياسية واحدة. لذلك فإن ترك مسافة غير مرمزة داخل مسار الهدف (Request-Target) أو نسيان الشرطة المائلة الأمامية في بدايته يكسر تقسيم سطر البداية ويجعل الخادم يرفض الطلب.
- تشويه صيغة إصدار البروتوكول: كتابة رمز إصدار البروتوكول (HTTP-Version) بمسافة بدلاً من الشرطة المائلة أو بحروف صغيرة يخالف الصيغة القياسية الإلزامية في السطر الأول.
- المسافات البادئة وأسطر التعليقات: لا يدعم بروتوكول
HTTPالنصي الخام إدراج أسطر تعليقات برمجية داخل الرسالة. كما أن وضع مسافة فارغة أو تعليق قبل سطر البداية يفسد تحليله فوراً. - وضع مسافة قبل النقطتين الرأسيتين: يحظر المعيار قطعياً وجود أي مسافة بين اسم الرأس والنقطتين الرأسيتين ويلزم الخادم برفض الطلب برمز
400 Bad Request. أما المسافة الواحدة بعد النقطتين الرأسيتين قبل قيمة الرأس فهي صحيحة ومستحسنة. - ترك مسافة داخل اسم الرأس بإسقاط الواصلة: تُربط الكلمات المركبة في أسماء الرؤوس مثل
Accept-LanguageوContent-Typeبواصلة متصلة دائماً. ولذلك فإن ترك مسافة داخل الاسم يكسر تحليل الرأس فوراً. - إغفال رأس المضيف الإجبارية: يشترط البروتوكول إرفاق رأس
Hostواحد بالضبط في كل طلب قياسي لتحديد النطاق المستهدف. ويؤدي نسيان هذا الرأس أو تكراره في الطلب الواحد إلى رفضه برمز400 Bad Requestكما يوضح المثال المقارن التالي:
# WRONG: Comment line, missing leading slash, unencoded space,
# missing version slash, space in header name, and no Host header:
// bad request example
GET my lessons/http.html HTTP 1.1
Accept Language : ar, en
# CORRECT: Valid start-line, encoded path, and valid headers:
GET /my%20lessons/http.html HTTP/1.1
Host: closetag.com
Accept-Language: ar, en
وإلى جانب أخطاء مقدمة الرسالة، تقع أخطاء شائعة أخرى عند الفصل بين الرؤوس وجسم الرسالة أو عند توصيف طول الجسم ونوعه:
- نسيان السطر الفارغ الفاصل: إرسال الجسم ملتصقاً بآخر رأس دون سطر
CRLFفارغ يجعل المحلل يقرأ أول سطر من الجسم كرأس فيفشل التحليل. كما أن نسيان السطر الفارغ في نهاية طلب خالٍ من الجسم يجعل الخادم يعلق منتظراً بقية الرؤوس. - عدم تطابق طول المحتوى مع حجم الجسم الفعلي: كتابة رقم في رأس
Content-Lengthأصغر من عدد البايتات الفعلي للجسم يؤدي إلى اقتطاع البيانات (Truncation) وبتر نهايتها. أما كتابة رقم أكبر من الحجم الفعلي فتجعل المستقبل ينتظر بايتات إضافية لن تصل أبداً حتى تنقضي مهلة الاتصال. - إغفال رأس نوع المحتوى أو عكس صيغتها: يوصي المعيار
RFC 9110(القسم8.3—SHOULD) بإرفاق رأسContent-Typeبصيغة النوع الرئيسي ثم النوع الفرعي مع كل رسالة تحمل جسماً؛ لأن إغفالها يجعل المستقبل يعامل البيانات كبايتات مجهولة (application/octet-stream) أو يرفض الطلب برمز415 Unsupported Media Type، كما أن عكس صيغتها يفسد تفسير الحمولة كما يبين المثال التالي:
# WRONG: Reversed MIME type (html/text), wrong Content-Length (10
# instead of 31 bytes), and missing Blank Line before the body:
POST /api/progress HTTP/1.1
Host: closetag.com
Content-Type: html/text
Content-Length: 10
{"course": "HTTP", "lesson": 3}
# CORRECT: Valid MIME type, exact 31-byte length, and Blank Line:
POST /api/progress HTTP/1.1
Host: closetag.com
Content-Type: application/json
Content-Length: 31
{"course": "HTTP", "lesson": 3}
وعلى المستوى المفاهيمي والبرمجي، يجب الحذر من افتراض أن كل رسالة HTTP لا بد أن تحتوي على جسم. فاستجابات 1xx و 204 No Content و 205 Reset Content و 304 Not Modified واستجابات HEAD يُحظر معيارياً أن تحمل أي جسم، كما أن طلبات GET و HEAD و DELETE لا تحمل جسماً ذا دلالة معيارية في الاستخدام القياسي. ومن الأخطاء البرمجية الشائعة أيضاً محاولة قراءة رسائل HTTP/1.1 عبر تقسيم النص عشوائياً عند كل سطر جديد؛ فالتحليل الصحيح يلتزم بقواعد تأطير الرسالة (Message Framing) التي تعتمد على فاصل CRLF المزدوج لنهاية الرأس، ثم على Transfer-Encoding (مثل chunked) أو طول البايتات في Content-Length لقراءة الجسم.
تحدي «لاقط الأخطاء» التفاعلي: اكتشف السطر المعطوب في 4 رسائل HTTP خام
اختبر دقة ملاحظتك الهندسية! تحتوي كل رسالة من الرسائل الأربع في الأداة التفاعلية أدناه على خطأ بنيوي أو صياغي واحد يؤدي إلى رفضها برمز 400 Bad Request أو اقتطاع بياناتها (مسافة قبل النقطتين، غياب Host، خطأ Content-Length مع العربية، أو غياب السطر الفارغ CRLF). انقر مباشرةً على السطر الذي يحمل الخطأ لاكتشافه وتصحيحه:
اختبار تطبيقي قصير: قس قدرتك على قراءة رسالة HTTP وتشخيصها بنفسك
قبل الانتقال إلى الاختبار التفاعلي في نهاية الدرس، اقرأ الرسالتين الخام الآتيتين بتمعن وحاول الإجابة عن الأسئلة التشخيصية الخمسة أدناه بنفسك:
# === Message [A]: Raw HTTP Request ===
POST /api/v1/auth/verify HTTP/1.1
Host: auth.closetag.com
Content-Type: application/json
Content-Length: 28
{"user": "ali", "otp": 4821}
# === Message [B]: Raw HTTP Response to a Conditional GET ===
HTTP/1.1 304 Not Modified
Date: Mon, 02 Nov 2026 12:50:00 GMT
ETag: "v9-bundle"
Content-Length: 1420
قارن قراءتك للرسالتين بالإجابات المعيارية الموثقة في الجدول الآتي:
| سؤال قراءة الرسالة وتشخيصها | القراءة الصحيحة والتفسير المعياري |
|---|---|
1. ما صيغة هدف الطلب في الرسالة [A]؟ وكيف يتحول سطر بدايتها في HTTP/2؟ |
الصيغة هي origin-form. وفي HTTP/2 يُستبدل سطر البداية ورأس Host بأربعة حقول زائفة داخل إطار HEADERS هي: method بقيمة POST، و scheme بقيمة https، و authority للنطاق، و path للمسار. |
2. هل قيمة 28 في رأس Content-Length للرسالة [A] مطابقة لطول الجسم الفعلي؟ |
نعم، مطابقة تماماً؛ فكائن JSON المرسل يتكون من أحرف ASCII قياسية يبلغ طولها 28 بايت بالضبط، فيقرأ الخادم الكائن كاملاً دون اقتطاع أو تعليق. |
3. كم بايت سيقرأ المتصفح في جسم الرسالة [B] بعد السطر الفارغ CRLF؟ |
صفر بايت (لا يوجد جسم إطلاقاً)؛ فرغم وجود رأس Content-Length بقيمة 1420، فإن رمز الاستجابة هو 304 Not Modified، وبموجب RFC 9112 تنتهي الرسالة فوراً عند السطر الفارغ، بينما تشير القيمة 1420 فقط إلى حجم الملف المخزن لو طُلب بفعل GET وفق RFC 9110. |
4. ماذا يحدث لو أُضيف رأس Transfer-Encoding بقيمة chunked إلى الرسالة [A] مع بقاء رأس Content-Length؟ |
ينشأ تعارض تأطير خطير يرتبط بثغرات تهريب الطلبات (Request Smuggling)؛ وبموجب RFC 9112 تجبُّ Transfer-Encoding رأس الطول ويوصى برفض الرسالة برمز 400 Bad Request أو إغلاق الاتصال، وإذا اختار الخادم الوسيط تمريرها فيجب عليه إلزاماً (MUST) حذف رأس Content-Length قبل تمريرها. |
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
تعلّمت في هذا الدرس أن كل تواصل في HTTP يتم عبر نوعين من الرسائل (الطلب والاستجابة)، وأن الرسالة تتكون من أربعة أقسام: سطر البداية، ورؤوس الرسالة، والسطر الفارغ الفاصل الإلزامي، وجسم الرسالة الاختياري الذي يُقاس طوله بعدد البايتات الفعلي (حيث يشغل كل حرف عربي بايتين في UTF-8)، كما تعرّفت على تحولها إلى إطاري HEADERS وDATA في HTTP/2 وHTTP/3 وفحصتها عملياً.
الخطوة التالية والدرس القادم
طبّق ما تعلمته الآن بحل المهام العملية وبنك الأسئلة التفاعلي أسفل الدرس، ثم انتقل مباشرةً إلى الدرس التالي في المسار: طلب HTTP (HTTP Request) لتتعمق في أفعال الطلب وبناء الطلبات الاحترافية.