Express.js / المتوسط: الوحدات والهوية والموائمات / الدرس 7
الموجهات ومسارات التركيب وحدود الوحدات
ركب واجهة معيارية مع الحفاظ على نطاق المعاملات وترتيب الوسائط وتفويض الكائن.
في هذه الصفحة
أهداف الدرس
- ميز مسار الموجه النسبي عن عنوان الطلب الأصلي.
- استخدم معاملات الأب بقصد واضح واحقن اعتمادات الوحدة.
الموجه تركيب وسائط ضمن نطاق
تنشئ express.Router نظام وسائط ومسارات قابلاً للتركيب، لا خادماً مستقلاً يستمع. اجمع المسارات حول قدرة مجال بدلاً من تقسيم الملفات اعتباطياً حسب طريقة HTTP. قد تملك وحدة المقررات موائمات إدخالها وشكل نتائجها العامة وتشترك في سياسة catalog محقونة. تركيبها عند /api/courses يجعل /:id مساراً نسبياً يضاف إلى تلك البادئة. حدد أين تقع المصادقة وتحليل الجسم وسياسة الكائن وترجمة الأخطاء حتى لا يغفل تركيب ثان شرطاً سابقاً. تتحقق فائدة التقسيم عندما يتضمن عقد الوحدة هذه الاعتمادات، لا عندما ينقل الأسطر إلى ملف آخر فقط.
صرح بوراثة معاملات المسار الأب
لا يرث الموجه الفرعي كل معاملات الأب تلقائياً. يحفظ mergeParams قيم req.params من الأب عندما يحتاجها التصميم، وعند تعارض الاسم ترجح قيمة الابن. يستخدم الجزء اسمين مختلفين، tenantId وcourseId، لتجنب الالتباس. يحدد مستأجر المسار النطاق المطلوب لكنه يحتاج مطابقة صلاحية الهوية المصادق عليها؛ وتتولى الخدمة المحقونة هذا القرار. يفترض الجزء وجود app وexpress وcatalog ولا يستورد حزمة أو يشغل خادماً. لا تحول وراثة المعاملات إلى ثقة بقيمة قدمها العميل، لأنها تنقل النص ولا تمنحه سلطة.
function makeCourseRouter(express,catalog) {
const router = express.Router({mergeParams:true});
router.get("/:courseId", async (req,res) => {
const card = await catalog.visibleCard({
principal:req.principal, tenantId:req.params.tenantId, id:req.params.courseId
});
if (!card) return res.status(404).json({code:"COURSE_NOT_FOUND"});
return res.json(card);
});
return router;
}
app.use("/tenants/:tenantId/courses", makeCourseRouter(express,catalog));
يحفظ mergeParams معامل tenantId، ويعرف الابن courseId. تبقى أهلية المستأجر والكائن من مسؤولية الخدمة.
اختر خصائص العنوان وفق معناها الموثق
داخل الموجه المركب تصف req.baseUrl مسار التركيب المطابق، وتحفظ req.originalUrl العنوان الأصلي، وتصف req.path المسار دون سلسلة الاستعلام. لا تجمعها دون فهم أو تجعل العنوان الأصلي قرار تفويض. قد يكشف تسجيله كاملاً قيم استعلام خاصة؛ فاستعمل معرف مسار آمناً وبيانات متحققاً منها في الرصد المعتاد. وتحتاج الروابط وإعادة التوجيه سياسة صريحة للأساس الخارجي، خصوصاً خلف الوكيل. مسار التركيب الداخلي ليس أصلاً عاماً موثوقاً تلقائياً، وقد يؤدي الخلط إلى روابط خاطئة أو كشف معلومات في السجلات.
قارن النطاق المطلوب بنطاق الهوية
ينمذج الشرط المحلي الكامل شرطاً سابقاً للمسار المتداخل: انتماء الهوية إلى المستأجر المطلوب. لا ينفذ ظهور الكائن ولا يثبت أصالة الهوية. يظهر اختبار النطاق نفسه بهويتين الفرق دون Express. قد تتضمن السياسة الحقيقية أدواراً مفوضة أو عضوية بدلاً من المساواة، لكن الاستثناء يحتاج قاعدة صريحة. لا تعتبر تسمية المستأجر في المسار دليلاً على العضوية، ولا تخزنها بحالة عامة قابلة للتغيير قد يستبدلها طلب آخر. يفيد هذا الفحص الضيق قبل اختبار سياسة الكائن الأكثر تفصيلاً.
function scopeAllowed(principal,requestedTenant) {
return principal.tenantId === requestedTenant;
}
console.assert(scopeAllowed({tenantId:"lab-a"},"lab-a"));
console.assert(!scopeAllowed({tenantId:"lab-b"},"lab-a"));
تنجح الهوية الأولى وتفشل الثانية وفق المساواة المحلية فقط؛ لم تختبر المصادقة أو سياسة catalog الكاملة.
نسق سياسة فشل الوحدة والتطبيق
يستطيع الموجه إنهاء نتيجة محلية أو تمرير فشل غير متوقع لمعالجة أخطاء التطبيق. وحّد الرموز العامة وتجنب معالجاً شاملاً داخل الوحدة يحجب مسارات غير معنية ركبت لاحقاً. تنتمي وسائط المعاملات إلى نطاق الموجه الموثق، ولا تصبح محققاً عاماً لكل معامل بالاسم نفسه. اختبر الوحدة باعتمادات بديلة ثم اختبر بادئة تركيبها ووراثة معاملاتها في الدمج الفعلي. لا يثبت نجاح شرط نطاق محلي مطابقة المسار أو موضع المحلل أو مسؤولية رد 404 النهائي.
الأخطاء الشائعة وإصلاحها
يختفي tenantId داخل الموجه الفرعي
- لماذا يحدث؟
- افترض التصميم وراثة معاملات الأب دون mergeParams.
- كيف تصلحه؟
- استخدم وراثة مقصودة وأسماء غير متعارضة.
- كيف تتجنب تكراره؟
- اختبر المسار المركب ببادئته الفعلية.
يتجاوز مسار المستأجر سياسة الوصول
- لماذا يحدث؟
- اختلط النطاق المطلوب بالمسموح.
- كيف تصلحه؟
- تحقق من أهلية الهوية في خدمة المجال المشتركة.
- كيف تتجنب تكراره؟
- اختبر هوية أخرى على المسار نفسه.
تحجب الوحدة مسارات تالية
- لماذا يحدث؟
- استهلك رد شامل طلبات خارج مسؤولية الوحدة.
- كيف تصلحه؟
- ضيق المعالج أو انقل مسؤولية غير المطابق لموضعها.
- كيف تتجنب تكراره؟
- راجع المطابقة والمرور عند كل تركيب.
اختبر فهمك
1. هل يفوض mergeParams المستأجر الأب؟
اعرض الحل المشروح
لا؛ يحفظ قيم المعاملات للابن وتبقى إدخال طلب. تقارن الخدمة النطاق بالهوية وتطبق سياسة الكائن. اختبر غياب الوراثة ومنع العضوية منفصلين، فلكل منهما سبب وعلاج مختلف.
2. ماذا يستقبل مصنع الموجه بدلاً من استيراد قاعدة عامة مضبوطة؟
اعرض الحل المشروح
يتلقى خدمة مجال ضيقة بأساليب ومسؤوليات سياسة موثقة. تحقن الاختبارات بديلاً اصطناعياً دون اتصال. يجمع مسؤول العملية الاعتمادات الحقيقية ويمتلك عمرها، فيعاد استخدام الوحدة دون تشغيل خدمات عند استيرادها.
أهم ما تعلمته
- يشمل تركيب الموجه النطاق والشروط السابقة وسلوك المرور.
- تبقى قيم المسار الموروثة إدخالاً غير موثوق.