محتويات الدورة

Express.js / المتوسط: الوحدات والهوية والموائمات / الدرس 11

الملفات الثابتة والقوالب وعقود التنزيل

افصل الأصول العامة عن توصيل الملفات المفوض، واهرب إخراج القالب وفق سياقه الفعلي.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • اختر جذور الملفات ومسؤولية المسار دون كشف مجلدات خاصة.
  • اشرح هروب القالب واسم التنزيل وحدود إكمال الرد.

المجلد الثابت قرار نشر

تخدم express.static ملفات تحت جذر نظام ملفات مضبوط. عامل كل ملف مؤهل يوضع هناك كمنشور عمداً وفق الخيارات؛ فهذا ليس نظام تفويض وثائق لكل كائن. أبق الرفع والأسرار والصادرات الخاصة وبيانات المصدر خارج الجذر. استعمل جذراً مطلقاً مقصوداً بدلاً من مجلد عمل قد يختلف بين بيئات التشغيل. يحدد ترتيب الوسائط مرور طلب الأصل لمعالج آخر. راجع سلوك الملفات المخفية صراحة، خصوصاً عند الانتقال إلى Express 5، ولا توسع الوصول لمجرد اختفاء ملف مخفي كان يظهر سابقاً. الفصل المادي يساعد على وضوح قرار النشر.

ركب جذراً عاماً معتمداً وحده

يستقبل الجزء جذراً راجع مسبقاً ويركبه عند /assets. توضح الخيارات رفض المخفي وضبط مرور المفقود؛ قيمها وفق سلوك المشروع المطلوب. أما التصدير الخاص فيحدد ببحث مجال مفوض ومعرف مصدر آمن، لا بضم مسار مستخدم إلى مجلد ثابت. اسم التنزيل في Content-Disposition بيانات عرض لا صلاحية. لا يجعل الاسم الغامض أو فرض التنزيل ملفاً خاصاً آمناً للنشر في جذر مشترك. يبقى المثال ضبطاً توضيحياً بلا قراءة نظام ملفات أو خادم، ولا يثبت أن محتويات مجلد حقيقي مناسبة للنشر.

javascript وسيط ملفات ثابتة محدود النطاق
app.use("/assets", express.static(publicAssetRoot,{
  dotfiles:"deny",
  fallthrough:false
}));

يمثل publicAssetRoot مجلداً مطلقاً محقوناً ومراجعاً. لا تقرأ ملفات ولا يشغل خادم ثابت هنا.

يعتمد الهروب على موضع إدراج النص

يتكامل Express مع محركات قوالب ولا يحدد لغة هروب عالمية. النص الآمن داخل HTML ليس آمناً تلقائياً داخل شيفرة أو URL أو سمة. اختر شكل الإخراج المهرب الموثق لمحركك وأبعد المحتوى غير الموثوق عن العرض الخام. لا تسمح للمستخدم باختيار اسم القالب أو حقن متغيرات تغير خيارات التصيير. ضع في res.locals نموذج عرض مقصوداً لا الطلب كله أو الكيان الداخلي. تحقق من الروابط والترميزات السياقية مستقلة عن هروب النص العادي، لأن تغيير السياق قد يحول القيمة من وصف بريء إلى محتوى تنفيذي.

عامل اسم التنزيل كقيمة عرض ضيقة

يختار النموذج المحلي اسم تنزيل ASCII من معرف تصدير معتم متحقق منه، ولا يستعمل مساراً يقدمه المستدعي أو يفتح ملفاً. ما زال على الموائم تفويض التصدير وحل هويته التخزينية بأمان واستعمال تسلسل ترويسة الإطار. يتجنب النموذج ادعاء أن تطبيع المسار يمنع كل اجتياز أو رابط رمزي. افصل مكان التخزين واسم العرض العام وأهلية الكائن؛ فدمجها يحول معامل اسم يبدو بسيطاً إلى قدرة قراءة غير مقصودة. الدليل هنا صحة بناء الاسم ضمن اتفاق محدد فقط، لا أمان نظام ملفات كامل.

javascript نموذج محلي كامل لاسم التنزيل
function exportLabel(id) {
  if (typeof id !== "string" || !/^e[0-9]{1,6}$/.test(id)) throw new Error("INVALID_EXPORT_ID");
  return `course-export-${id}.csv`;
}
console.assert(exportLabel("e17") === "course-export-e17.csv");
let rejected=false; try {exportLabel("../private");} catch {rejected=true;}
console.assert(rejected);

ينتج e17 اسماً ثابت الصيغة ويرفض الإدخال الشبيه بمسار. لم يختبر البحث التخزيني أو التفويض أو ترميز الترويسة.

عالج الفقد والفشل المتأخر بوضوح

قد يختفي الملف بين قراءة بياناته وتوصيله، أو ينقطع العميل بعد إرسال الترويسات. اتبع عقد إكمال sendFile أو download الموثق ومرر الخطأ دون محاولة رد ثان. تتبع الإلغاء وحرر الموارد عند انتهاء التوصيل. راجع نوع المحتوى والتنزيل والمخبأ والتفويض معاً لكل فئة وثيقة. اختبر الفقد والمنع والتوصيل الجزئي بدمج معزول مأذون. يفحص المقرر دالة الاسم فقط ولا يشغل القالب أو خدمة القرص أو تفسير المتصفح أو نقل ملف حقيقي. لا تجعل نجاح تجهيز البيانات الوصفية دليلاً على اكتمال التوصيل.

الأخطاء الشائعة وإصلاحها

تظهر صادرات خاصة تحت عنوان الأصول

لماذا يحدث؟
وضع التخزين الخاص داخل جذر عام.
كيف تصلحه؟
افصل التخزين وقدم التصدير ببحث كائن مفوض.
كيف تتجنب تكراره؟
راجع حالة نشر كل مجلد تحت الجذر.

يصل محتوى المستخدم لموضع قالب خام

لماذا يحدث؟
تجاوز الهروب أو افترض استقلاله عن السياق.
كيف تصلحه؟
استخدم الهروب المناسب ونموذج عرض آمن.
كيف تتجنب تكراره؟
اختبر سياقات النص والسمة والعنوان منفصلة.

يسبب خطأ تنزيل متأخر رداً آخر

لماذا يحدث؟
تجاهل حد الالتزام بالتوصيل.
كيف تصلحه؟
اتبع ردود الإكمال والخطأ ومعالجة headersSent.
كيف تتجنب تكراره؟
اختبر الانقطاع وسباق الفقد معزولاً.

اختبر فهمك

1. لماذا ليس اسم التنزيل رمز تفويض تخزين؟

اعرض الحل المشروح

يصف العرض للعميل، ويحدد الخادم مستقلاً الكائن المؤهل ومكانه. لا يثبت الاسم اللطيف أو الغامض ملكية أو نطاق قراءة. افصل المعرف ومفتاح التخزين والاسم، واستعمل تسلسل الترويسة الموثق لا دمج نص غير موثوق.

2. هل يحمي هروب نص HTML قيمة توضع داخل JavaScript؟

اعرض الحل المشروح

ليس عموماً؛ تختلف قواعد التحليل بحسب السياق. تجنب وضع غير الموثوق في شيفرة تنفيذية واتبع نقل البيانات الآمن الموثق. لا يصادق اختبار نص HTML سياق الشيفرة أو السمة أو URL، فسم السياق المحدد بالمراجعة.

أهم ما تعلمته

  • يحتاج النشر الثابت وتوصيل الوثيقة المفوض مسؤوليتين مختلفتين.
  • يتبع ترميز الإخراج وإكمال الملف السياق والدورة الفعليين.

المراجع الرسمية