Express.js / الأساسي: مسؤولية الطلب والاستجابة / الدرس 2
المسارات والطرق وعقود المعاملات
طابق المسار وطريقة HTTP بدقة، وعامل معاملات المسار وقيم الاستعلام كإدخال غير موثوق.
في هذه الصفحة
أهداف الدرس
- ميز معاملات المسار وسلسلة الاستعلام وجسم الطلب.
- طبق تحويل المعرف الصارم وصياغة مسارات Express 5 بقصد واضح.
يجمع المسار طريقة وعقداً للعنوان
تسجل app.get سلوك مسار GET، وتسجل app.post طريقة مختلفة ولو تطابق نص المسار. تستخدم المطابقة جزء المسار من URL، ولا تعد سلسلة الاستعلام جزءاً من نمط المسار. يظل /courses/c1?locale=ar مسار مقرر مع إدخال استعلام منفصل. احفظ سلوك القراءة الآمن تحت GET، وعرف الكتابة بطرق مناسبة مع فحوص المجال. لا ينفذ تغيير الطريقة وحده التفويض أو الحماية من CSRF أو سياسة تحمل إعادة الطلب. ينبغي أن يظل معنى كل طريقة واضحاً للعميل ولمن يراجع التطبيق.
اقرأ كل قيمة من مصدرها المعلن
يقرأ الجزء id من req.params وlocale من req.query ثم يستدعي خدمة مجال اصطناعية. يؤثر إعداد محلل سلسلة الاستعلام في شكل req.query، ولذلك لا تضمن أن كل قيمة سلسلة واحدة. يرفض فحص locale الصريح المصفوفات والكائنات بدلاً من تمريرها إلى داخل التطبيق. يحدد العقد الحقيقي هل يتجاهل مفاتيح استعلام غير معروفة أو يرفضها. يبقى المسار غير قابل للتشغيل لأن app وcatalog اعتمادان توضيحيان، ولا ينشأ خادم HTTP. فصل مصادر الإدخال يجعل التحقق أقرب إلى الحد الذي وصلت منه القيمة.
app.get("/courses/:id", async (req,res) => {
const locale = req.query.locale ?? "en";
if (typeof locale !== "string" || !["en","ar"].includes(locale)) {
return res.status(400).json({code:"INVALID_LOCALE"});
}
const card = await catalog.publicCard(req.params.id, locale);
if (!card) return res.status(404).json({code:"COURSE_NOT_FOUND"});
return res.json(card);
});
يكون الافتراض en عند غياب locale، وتقبل السلسلة ar. ترفض المصفوفة أو الكائن أو السلسلة غير المدعومة بالرد 400 قبل البحث.
استعمل قواعد المسار الخاصة بالإصدار المختار
غير Express 5 صياغة أنماط المسار النصية مقارنة بالإصدار الرابع. تحتاج المحارف الشاملة أسماء، وتستعمل الأجزاء الاختيارية الأقواس المعقوفة بدلاً من أنماط علامة الاستفهام القديمة. وقد ينتج المحرف الشامل المسمى مصفوفة مقاطع، فلا تفترض أن كل معامل سلسلة واحدة. راجع دليل الانتقال الرسمي للنمط المحدد وللفرق بين نمط يستثني الجذر وآخر يشمله. لا تنسخ وصفة قديمة لمسار شامل إلى تطبيق جديد دون فحص مسارات ممثلة ومقاطع مفقودة ومسار الجذر. صحة النمط جزء من عقد العناوين العام لا مجرد تفصيل صياغة.
ارفض التحويل العددي الجزئي
تقبل parseInt بادئة عددية، وقد تحول 12notes إلى 12 إذا استخدمت دون فحص العقد أولاً. لا يقبل المحلل المحلي التالي إلا معرفات عشرية موجبة ضمن مجال الأعداد الصحيحة الآمنة، ويرفض الأصفار البادئة بقصد. هذا اتفاق محلي للتطبيق لا قاعدة عالمية للمعرفات؛ فواجهات كثيرة ينبغي أن تحفظ معرفات نصية معتمة. المهم أن تعلن الصياغة والمدى قبل التحويل، ثم تختبر النصوص المخالفة والصفر والقيم الضخمة، بدلاً من ترك الإكراه الضمني في JavaScript يقرر هوية الكائن الذي سيجلبه التطبيق.
function positiveId(text) {
if (typeof text !== "string" || !/^[1-9][0-9]*$/.test(text)) return null;
const value = Number(text);
return Number.isSafeInteger(value) ? value : null;
}
console.assert(positiveId("12") === 12);
console.assert(positiveId("12notes") === null);
console.assert(positiveId("0") === null);
console.assert(positiveId("9007199254740992") === null);
تعيد العينة الصحيحة 12 وترفض العينات الثلاث بقيمة null. لا يحاكي الاختبار فك ترميز Express أو مطابقة المسار.
رتب المسارات المحددة وحدد سلوك غير المطابق
يفحص Express المعالجات حسب ترتيب تسجيلها، فيمكن لمسار معامل واسع أن يلتقط مقطعاً ثابتاً أردته لمعالج أكثر تحديداً. ضع /courses/search قبل /courses/:id إذا كان ذلك جزءاً من العقد، أو صمم عناوين أقل التباساً. تعالج النهاية العادية لسلسلة الوسائط المسار غير الموجود عادة، لا معالج أخطاء ينتظر استثناء. وثق هل ترد الطرق غير المدعومة بسياسة 405 صريحة أو تصل إلى رد غير المطابق. اختبر المطابقة وسلوك الطريقة منفصلين عن حالة وجود المسار مع غياب السجل في خدمة المجال.
الأخطاء الشائعة وإصلاحها
تعامل search كمعرف مقرر
- لماذا يحدث؟
- سجل مسار معامل واسع قبل مسار البحث الثابت.
- كيف تصلحه؟
- قدم المسار المحدد أو أعد تصميم العناوين الملتبسة.
- كيف تتجنب تكراره؟
- احتفظ بعينات للمقاطع الثابتة المحجوزة.
تصل 12notes إلى السجل 12
- لماذا يحدث؟
- استبدل التحقق الصارم بتحليل بادئة عددية.
- كيف تصلحه؟
- تحقق من النص كله ومداه قبل تحويله.
- كيف تتجنب تكراره؟
- اختبر النص اللاحق وحدود العدد غير الآمن.
يصل كائن استعلام إلى خدمة تنتظر سلسلة
- لماذا يحدث؟
- وثق شكل req.query دون تحقق.
- كيف تصلحه؟
- افحص النوع والقيم المسموحة عند حد الطلب.
- كيف تتجنب تكراره؟
- اختبر المفاتيح المكررة والإدخال البنيوي وفق المحلل المختار.
اختبر فهمك
1. لماذا لا يتضمن نمط مسار /courses/c1?locale=ar الجزء ?locale؟
اعرض الحل المشروح
يطابق النمط المسار، وتصل locale عبر محلل الاستعلام وتحتاج عقد إدخال مستقلاً. يمكن استدعاء المسار بقيم كثيرة دون تسجيل كل شكل URL. افحص نوع القيمة ومفرداتها؛ فمطابقة /courses/:id لا تصادق عضو الاستعلام أو تجعله آمناً للخدمة التابعة.
2. هل يجب أن ترفض كل واجهة الأصفار البادئة كما يفعل المحلل المحلي؟
اعرض الحل المشروح
لا، فهذا اتفاق المثال المعلن. قد تحفظ واجهة ذات معرفات نصية معتمة 0012 باعتبارها مختلفة عن 12. اختر معنى الهوية من المجال والمصدر وتحقق منه باتساق. المقصود تجنب التحويل الجزئي العرضي، لا فرض تصميم هوية عددي واحد على كل تطبيق.
أهم ما تعلمته
- تثبت مطابقة المسار والتحقق من الإدخال حقيقتين مختلفتين.
- تستحق صياغة مسارات Express 5 وأشكال معاملاتها اختبارات انتقال صريحة.