متوفر أيضًا بلغات أخرى: English · Español · Português · Français
طلبات المدى في HTTP: ماذا تطلب ترويسة Range وماذا يعود
اكتب ترويسة Range وحجم ملف، وانظر البايتات بالضبط، ورمز الحالة، وترويسة Content-Range التي سيرسلها خادم مطابق.
ما طلب المدى في HTTP؟
طلب المدى يسأل الخادمَ جزءًا من ملف بدل الملف كله. وهكذا يقفز مشغّل الفيديو إلى الدقيقة العشرين بلا تنزيل التسع عشرة قبلها، وهكذا يُستأنف تنزيلٌ انقطع، وهكذا يرسم عارض PDF الصفحة الأربعمئة من مستند كبير بلا جلب التسع والتسعين وثلاثمئة الأولى. فيرسل العميل ترويسة Range تسمّي إزاحات البايتات التي يريدها؛ والخادم الذي يستجيب يجيب بـ206 Partial Content بتلك البايتات وترويسة Content-Range تقول أيها كانت.
والصياغة وحدةُ مدى، ثم علامة يساوي، ثم مدى واحد أو أكثر تفصلها الفواصل. والوحدة المعرَّفة واحدة — bytes — والإزاحات شاملة وتبدأ من صفر، فـbytes=0-499 هي أول خمسمئة بايت، وbytes=500-999 هي الخمسمئة التالية. وللإزاحة الأخيرة أن تُحذف، فتعني حينئذ كل شيء من هناك إلى النهاية.
والصيغة التي توقع الناس هي التي لا شيء قبل شرطتها. فـbytes=-500 ليست خطأً ولا إزاحةً بسالب خمسمئة: بل تسمّيها المواصفة مدى لاحقة وتعرّفها بلفظها بأنها آخر N وحدة من المورد. فهي تطلب آخر خمسمئة بايت، وbytes=0-0,-1 تطلب أول بايت وآخر بايت، وذلك مثال المواصفة نفسها.
كيف تستعملها
- اكتب ترويسة Range وحجم ملف. الترويسة كما سترسلها، بمسافات بعد الفواصل أو بغيرها — فأمثلة المواصفة نفسها فيها مسافات. والحجم هو طول الملف كله، لأن كل إزاحة تُحسب عليه.
- اقرأ سطر الحالة. 206 تعني أن المديات نُفِّذت، و416 تعني أنه تعذّر تنفيذ أي منها، والأداة تعرض ترويسة Content-Range التي سيحملها كل جواب. وأزرار الأمثلة تغطي مدى لاحقة، ومدًى عاديًّا، وطلبًا من جزأين، وآخر يقع بعد نهاية الملف.
- انظر إلى الجدول. فهو يسرد أول بايت وآخر بايت بالضبط لكل جزء سيصل، وحجمه، وترويسة Content-Range التي يحملها ذلك الجزء. وتحته تشرح الاستنتاجات ما تقوله المواصفة عمّا طلبتَه.
وللخادم أن يهملك
هذا أول ما يحسن استقراره في الذهن، وهو مقول بلا مواربة: للخادم أن يهمل ترويسة Range. لا أن يرفضها ولا أن يخطئ — بل أن يهملها، ويجيب بـ200 والملف كله كأن الترويسة لم تُرسَل قط. وذلك جواب مطابق، فكل عميل يطلب مديات عليه أن يحسن استقبال جسم كامل بدل جزئي.
وتعيد المواصفة الأمر من الجهة الأخرى وهي تتحدث عن 416: فلأن الخوادم حرّة في إهمال Range، تجيب تطبيقات كثيرة بالمورد كله في 200، ومن ثَمّ تخلص إلى أن العملاء لا يمكنهم الاعتماد على تلقّي 416 ولو كان أنسب ما يكون. فإن كان منطق الاستئناف عندك يعدّ كل ما ليس 206 إخفاقًا فسينكسر أمام خادم مطابق تمامًا.
والنطاق كذلك أضيق مما يفترض أكثر الناس. فمعالجة المديات معرَّفة لطريقة واحدة بالضبط: على الخادم أن يهمل ترويسة Range في طلب لا يعرف طريقته أو لم تُعرَّف له معالجة مديات، وGET هي الطريقة الوحيدة التي تعرّفها لها المواصفة. فـRange في POST ملزَمة بألّا تفعل شيئًا.
المدى الواحد والمديان جوابان مختلفان
اطلب مدًى واحدًا تنل 206 وذلك المدى جسمًا، وترويسة Content-Range في الأعلى تقول أي البايتات ومن أي مجموع. واطلب اثنين يتغيّر الشكل كله: فعلى الخادم أن يرسل محتوى multipart/byteranges، مع معامل boundary في Content-Type، ويصل كل مدى جزءًا قائمًا بذاته بترويساته الخاصة.
وهنا القاعدة التي تفاجئ الجميع تقريبًا، وهي MUST NOT لا مسألة ذوق: على الخادم ألّا يضع ترويسة Content-Range في قسم ترويسات استجابةٍ متعددة الأجزاء، لأن ذلك الحقل يذهب داخل كل جزء. فالشفرة التي تقرأ Content-Range من الاستجابة لتعرف ما وصلها لن تقرأ شيئًا البتة لحظة إضافة مدًى ثانٍ. والمنع يجري في الاتجاه الآخر كذلك: على الخادم ألّا يلفّ مدًى واحدًا في تنسيق متعدد الأجزاء، لأن العميل الذي طلب جزءًا واحدًا قد لا يحسن قراءة المتعدد أصلًا.
وثمة إذنان آخران يحسن معرفتهما قبل إرسال قائمة طويلة. فللخادم أن يدمج المديات المتداخلة، أو التي يفصلها فراغ أصغر من كلفة إرسالها منفصلة، وله ذلك بلا التزام بالترتيب الذي وردت به في ترويستك — فما يعود لا يلزم أن يطابق ما طلبت، لا عددًا ولا تسلسلًا. والتنسيق ليس مجانًا: فالمواصفة تقدّر الكلفة بين الأجزاء بنحو ثمانين بايتًا، وتلاحظ أن نقل أجزاء صغيرة كثيرة متفرقة قد يكون أقل كفاءة من نقل المورد كله. والأداة تجمع لك ذلك وتنبّهك حين يقع.
ما لا تخبرك به هذه الأداة
هذه تستخرج معنى الترويسة. ولا تكلّم خادمك. فالمتصفح لا يستطيع أن يرسل طلبًا إلى مصدر آخر ويقرأ لك ترويسات استجابته بلا تعاون ذلك الخادم، فلا شيء هنا يُنزَّل: وحجم الملف هو الرقم الذي كتبتَه لا رقمٌ مقيس. ولترى ما يفعله خادم حقيقي فاستعمل لوحة الشبكة في متصفحك أو طلبًا من سطر الأوامر بالترويسة موضوعةً بيدك.
ولا تستطيع أن تخبرك أيدعم الخادم المديات أصلًا. فذلك يُعلَن بترويسة Accept-Ranges في استجابة عادية، ولأن للخادم أن يهمل Range على أي حال، فالجواب اليقيني الوحيد أن تطلب مدًى وترى ما يعود. فـ206 تعني نعم، و200 تعني إما لا وإما نعم لكن ليس هذه المرة.
وثمة تبسيط في الحساب. فإزاحات البايتات في HTTP بلا سقف، والمواصفة تحذّر صراحةً من وجوب توقّع أعداد عشرية هائلة ومنع أخطاء تجاوز الأعداد الصحيحة. وهذه الصفحة تعمل بأعداد جافاسكربت العادية، وهي دقيقة إلى نحو تسعة كوادريليونات — أبعد بكثير من أي ملف حقيقي، لكنها ليست بلا حدّ، فالإزاحة الضخمة عمدًا ستفقد دقتها هنا على نحو لا يفقده خادم متأنٍّ.
وأخيرًا، طلبات المدى المشروطة خارج النطاق. فالاستئناف الحقيقي يقرن Range عادةً بـIf-Range ليتحقق الخادم أن الملف لم يتغيّر من تحتك ويرسل الكل إن تغيّر. وتلك آلية مستقلة بقواعدها، وهذه الصفحة تجيب فقط عن أي البايتات يسمّيها Range بعينه.
لماذا هي مجانية؟
تحليل ترويسة وحسابُ إزاحات بايتات يجري في متصفحك. ولا خادم في الأمر، فلا شيء يُحاسَب عليه ولا حساب يُنشأ.
ولا يُرفع شيء ولا يُنزَّل شيء. أعد تحميل الصفحة تجدها قد نسيت ما كتبتَه.