Node.js

التوجيه و Middleware في Express.js — دليل شامل 2026

📅 2026-11-07⏱ 8 دقائق قراءة
في المقال السابق، تعلمت أساسيات Express.js. الآن سنتعمق في **التوجيه (Routing)** و **Middleware** — وهما ما يجعل تطبيقك **منظماً واحترافياً**. في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم التوجيه والميدل وير، مع تمارين وحلول. ## ما هو التوجيه (Routing)؟ **التوجيه** هو تحديد **كيف يستجيب التطبيق** لطلبات المستخدم. **الصيغة:** ```javascript app.METHOD(PATH, HANDLER); ``` **مثال:** ```javascript app.get("/users", (req, res) => { res.json({ users: [] }); }); ``` ## مشكلة المسارات المتعددة **عندما يكبر التطبيق:** ```javascript // كل شيء في index.js app.get("/users", ...); app.post("/users", ...); app.get("/users/:id", ...); app.put("/users/:id", ...); app.delete("/users/:id", ...); app.get("/posts", ...); app.post("/posts", ...); // ... 100+ مسار ``` **المشكلة:** الملف يصبح **ضخماً** و **صعب الصيانة**. ## الحل: Express Router **Express Router** يسمح بتقسيم المسارات إلى **ملفات منفصلة**. ### 1. بنية المشروع ``` my-app/ ├── routes/ │ ├── users.js │ ├── posts.js │ └── products.js ├── index.js └── package.json ``` ### 2. إنشاء Router **`routes/users.js`:** ```javascript const express = require("express"); const router = express.Router(); // GET /users router.get("/", (req, res) => { res.json([{ id: 1, name: "أحمد" }]); }); // POST /users router.post("/", (req, res) => { res.status(201).json({ success: true }); }); // GET /users/:id router.get("/:id", (req, res) => { res.json({ id: req.params.id }); }); module.exports = router; ``` ### 3. استخدام Router في التطبيق **`index.js`:** ```javascript const express = require("express"); const app = express(); // استيراد Routes const usersRouter = require("./routes/users"); const postsRouter = require("./routes/posts"); app.use(express.json()); // ربط Routes app.use("/users", usersRouter); app.use("/posts", postsRouter); app.listen(3000, () => console.log("🚀 على http://localhost:3000")); ``` **النتيجة:** - `GET /users` → يعمل - `GET /users/1` → يعمل - `POST /users` → يعمل - `GET /posts` → يعمل **🎉 الكود أصبح منظماً!** ## مثال كامل: 3 Routers ### `routes/users.js`: ```javascript const express = require("express"); const router = express.Router(); let users = [ { id: 1, name: "أحمد", email: "[email protected]" }, { id: 2, name: "محمد", email: "[email protected]" }, ]; // جلب كل المستخدمين router.get("/", (req, res) => { res.json(users); }); // جلب مستخدم واحد router.get("/:id", (req, res) => { const user = users.find((u) => u.id === parseInt(req.params.id)); if (!user) return res.status(404).json({ error: "غير موجود" }); res.json(user); }); // إضافة مستخدم router.post("/", (req, res) => { const { name, email } = req.body; const newUser = { id: Date.now(), name, email }; users.push(newUser); res.status(201).json(newUser); }); // تحديث مستخدم router.put("/:id", (req, res) => { const user = users.find((u) => u.id === parseInt(req.params.id)); if (!user) return res.status(404).json({ error: "غير موجود" }); Object.assign(user, req.body); res.json(user); }); // حذف مستخدم router.delete("/:id", (req, res) => { users = users.filter((u) => u.id !== parseInt(req.params.id)); res.status(204).send(); }); module.exports = router; ``` ### `routes/posts.js`: ```javascript const express = require("express"); const router = express.Router(); let posts = [ { id: 1, title: "تعلم Node.js", content: "..." }, { id: 2, title: "تعلم Express", content: "..." }, ]; router.get("/", (req, res) => { res.json(posts); }); router.get("/:id", (req, res) => { const post = posts.find((p) => p.id === parseInt(req.params.id)); if (!post) return res.status(404).json({ error: "غير موجود" }); res.json(post); }); router.post("/", (req, res) => { const newPost = { id: Date.now(), ...req.body }; posts.push(newPost); res.status(201).json(newPost); }); module.exports = router; ``` ### `index.js`: ```javascript const express = require("express"); const app = express(); app.use(express.json()); app.use("/api/users", require("./routes/users")); app.use("/api/posts", require("./routes/posts")); app.listen(3000, () => console.log("🚀 على http://localhost:3000")); ``` ## تنظيم متقدم: Controllers **لفصل المنطق عن المسارات:** ``` my-app/ ├── routes/ │ └── users.js ├── controllers/ │ └── userController.js ├── models/ │ └── user.js └── index.js ``` ### `controllers/userController.js`: ```javascript let users = [ { id: 1, name: "أحمد" }, ]; exports.getAllUsers = (req, res) => { res.json(users); }; exports.getUserById = (req, res) => { const user = users.find((u) => u.id === parseInt(req.params.id)); if (!user) return res.status(404).json({ error: "غير موجود" }); res.json(user); }; exports.createUser = (req, res) => { const newUser = { id: Date.now(), ...req.body }; users.push(newUser); res.status(201).json(newUser); }; exports.updateUser = (req, res) => { const user = users.find((u) => u.id === parseInt(req.params.id)); if (!user) return res.status(404).json({ error: "غير موجود" }); Object.assign(user, req.body); res.json(user); }; exports.deleteUser = (req, res) => { users = users.filter((u) => u.id !== parseInt(req.params.id)); res.status(204).send(); }; ``` ### `routes/users.js`: ```javascript const express = require("express"); const router = express.Router(); const userController = require("../controllers/userController"); router.get("/", userController.getAllUsers); router.get("/:id", userController.getUserById); router.post("/", userController.createUser); router.put("/:id", userController.updateUser); router.delete("/:id", userController.deleteUser); module.exports = router; ``` **الفائدة:** **Routes** للتوجيه فقط، **Controllers** للمنطق. ## Middleware المتقدم ### 1. Middleware للتسجيل ```javascript function logger(req, res, next) { const now = new Date().toISOString(); console.log(`[${now}] ${req.method} ${req.url}`); next(); } app.use(logger); ``` ### 2. Middleware للمصادقة ```javascript function auth(req, res, next) { const token = req.headers.authorization; if (!token) { return res.status(401).json({ error: "غير مصرح" }); } try { const decoded = jwt.verify(token, "secret"); req.user = decoded; next(); } catch (error) { res.status(401).json({ error: "توكن غير صالح" }); } } // استخدامه على مسار معين: app.get("/profile", auth, (req, res) => { res.json(req.user); }); ``` ### 3. Middleware للتحقق ```javascript function validateUser(req, res, next) { const { name, email } = req.body; if (!name || name.length < 2) { return res.status(400).json({ error: "الاسم قصير" }); } if (!email || !email.includes("@")) { return res.status(400).json({ error: "البريد غير صحيح" }); } next(); } app.post("/users", validateUser, (req, res) => { res.json({ success: true }); }); ``` ### 4. Middleware للمعدل (Rate Limiting) ```javascript const rateLimit = require("express-rate-limit"); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 دقيقة max: 100, // 100 طلب message: "تم تجاوز الحد، حاول لاحقاً", }); app.use("/api", limiter); ``` ### 5. Middleware للأخطاء ```javascript app.use((err, req, res, next) => { console.error("خطأ:", err.message); const status = err.status || 500; res.status(status).json({ error: err.message || "خطأ في السيرفر", }); }); ``` ## ترتيب Middleware **⚠️ الترتيب مهم جداً!** ```javascript const express = require("express"); const app = express(); // 1. Middleware عام app.use(express.json()); app.use(logger); app.use(cors()); // 2. Static files app.use(express.static("public")); // 3. Routes app.use("/api/users", usersRouter); app.use("/api/posts", postsRouter); // 4. 404 (بعد كل المسارات) app.use((req, res) => { res.status(404).json({ error: "المسار غير موجود" }); }); // 5. Error Handler (الأخير دائماً) app.use((err, req, res, next) => { res.status(500).json({ error: err.message }); }); ``` ## Middleware مخصص ### 1. Middleware على مستوى التطبيق ```javascript app.use((req, res, next) => { req.startTime = Date.now(); next(); }); ``` ### 2. Middleware على مستوى Router ```javascript const router = express.Router(); router.use((req, res, next) => { console.log("Router middleware"); next(); }); ``` ### 3. Middleware على مسار محدد ```javascript app.get("/admin", authMiddleware, (req, res) => { res.send("لوحة التحكم"); }); ``` ## تمارين عملية ### تمرين 1: Router بسيط أنشئ Router للمستخدمين. **الحل:** ```javascript // routes/users.js const express = require("express"); const router = express.Router(); router.get("/", (req, res) => res.json([])); router.post("/", (req, res) => res.status(201).json({})); module.exports = router; ``` ```javascript // index.js app.use("/api/users", require("./routes/users")); ``` ### تمرين 2: 3 Routers أنشئ Routers للمستخدمين والمنتجات والطلبات. **الحل:** ```javascript app.use("/api/users", require("./routes/users")); app.use("/api/products", require("./routes/products")); app.use("/api/orders", require("./routes/orders")); ``` ### تمرين 3: Controller افصل منطق المسار في Controller. **الحل:** ```javascript // controllers/userController.js exports.getAll = (req, res) => res.json([]); // routes/users.js const ctrl = require("../controllers/userController"); router.get("/", ctrl.getAll); ``` ### تمرين 4: Middleware للتسجيل أضف Middleware يسجّل الوقت. **الحل:** ```javascript app.use((req, res, next) => { console.log(new Date().toISOString(), req.method, req.url); next(); }); ``` ### تمرين 5: Middleware للمصادقة أضف Middleware يتحقق من توكن. **الحل:** ```javascript function auth(req, res, next) { if (!req.headers.authorization) { return res.status(401).json({ error: "غير مصرح" }); } next(); } app.get("/admin", auth, (req, res) => res.send("محمي")); ``` ### تمرين 6: Middleware للتحقق تحقق من بيانات المستخدم. **الحل:** ```javascript function validate(req, res, next) { if (!req.body.name) { return res.status(400).json({ error: "الاسم مطلوب" }); } next(); } ``` ### تمرين 7: 404 Handler أضف معالج 404. **الحل:** ```javascript app.use((req, res) => { res.status(404).json({ error: "غير موجود" }); }); ``` ### تمرين 8: API كامل ابنِ API كامل مع Routers و Controllers. **الحل:** (راجع المثال الكامل أعلاه) ## حل المشاكل الشائعة ### 🔴 المشكلة 1: Router لا يعمل **السبب:** نسيت `app.use()`. **الحل:** ```javascript app.use("/api/users", usersRouter); ``` ### 🔴 المشكلة 2: Middleware لا يعمل **السبب:** لم تستدعِ `next()`. **الحل:** ```javascript function middleware(req, res, next) { // ... next(); // ← مهم } ``` ### 🔴 المشكلة 3: 404 لجميع المسارات **السبب:** 404 Handler قبل المسارات. **الحل:** ضعه **بعد** كل المسارات. ### 🔴 المشكلة 4: Error Handler لا يعمل **السبب:** عدد المعاملات خاطئ. **الحل:** يجب أن يكون **4 معاملات**: ```javascript app.use((err, req, res, next) => { ... }); ``` ### 🔴 المشكلة 5: CORS **الحل:** ```bash npm install cors ``` ```javascript const cors = require("cors"); app.use(cors()); ``` ## جدول أنواع Middleware <table> <thead> <tr> <th>النوع</th> <th>الوصف</th> <th>مثال</th> </tr> </thead> <tbody> <tr> <td><strong>Application</strong></td> <td>على كل التطبيق</td> <td><code>app.use()</code></td> </tr> <tr> <td><strong>Router</strong></td> <td>على Router</td> <td><code>router.use()</code></td> </tr> <tr> <td><strong>Route</strong></td> <td>على مسار محدد</td> <td><code>app.get(path, mw)</code></td> </tr> <tr> <td><strong>Error</strong></td> <td>معالجة الأخطاء</td> <td><code>(err, req, res, next)</code></td> </tr> <tr> <td><strong>Built-in</strong></td> <td>مدمج</td> <td><code>express.json()</code></td> </tr> <tr> <td><strong>Third-party</strong></td> <td>خارجي</td> <td><code>cors, morgan</code></td> </tr> </tbody> </table> ## قائمة تحقق نهائية <table> <thead> <tr> <th>المهمة</th> <th>الحالة</th> </tr> </thead> <tbody> <tr> <td>فهم Express Router</td> <td>⬜</td> </tr> <tr> <td>إنشاء Routers منفصلة</td> <td>⬜</td> </tr> <tr> <td>فصل Controllers عن Routes</td> <td>⬜</td> </tr> <tr> <td>فهم Middleware</td> <td>⬜</td> </tr> <tr> <td>Middleware للمصادقة والتحقق</td> <td>⬜</td> </tr> <tr> <td>ترتيب Middleware الصحيح</td> <td>⬜</td> </tr> <tr> <td>حل التمارين الثمانية</td> <td>⬜</td> </tr> </tbody> </table> ## ماذا بعد هذا المقال؟ الآن بعد أن أتقنت التوجيه و Middleware، أنت جاهز للمقال التالي: 1. **بناء REST API** — واجهات احترافية. 2. **قواعد البيانات (MongoDB)** — تخزين البيانات. 3. **المصادقة (JWT)** — تسجيل الدخول. ## الخلاصة في هذا المقال، تعلمت: - ✅ Express Router. - ✅ تنظيم المشروع (Routes, Controllers). - ✅ Middleware المتقدم. - ✅ ترتيب Middleware الصحيح. - ✅ معالجة الأخطاء. - ✅ 404 Handler. - ✅ حل 8 تمارين عملية. **تذكر:** التوجيه و Middleware هما ما يجعل تطبيقك **منظماً واحترافياً**.