التوجيه و Middleware في Express.js — دليل شامل 2026
دليل عملي مفصل للتوجيه (Routing) و Middleware في Express.js — Router، تنظيم المسارات، مع تمارين وحلول
في المقال السابق، تعلمت أساسيات Express.js. الآن سنتعمق في التوجيه (Routing) و Middleware — وهما ما يجعل تطبيقك منظماً واحترافياً.
في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم التوجيه والميدل وير، مع تمارين وحلول.
ما هو التوجيه (Routing)؟
التوجيه هو تحديد كيف يستجيب التطبيق لطلبات المستخدم.
الصيغة:
app.METHOD(PATH, HANDLER);
مثال:
app.get("/users", (req, res) => {
res.json({ users: [] });
});
مشكلة المسارات المتعددة
عندما يكبر التطبيق:
// كل شيء في 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:
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:
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:
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:
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:
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:
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:
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 للتسجيل
function logger(req, res, next) {
const now = new Date().toISOString();
console.log(`[${now}] ${req.method} ${req.url}`);
next();
}
app.use(logger);
2. Middleware للمصادقة
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 للتحقق
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)
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 دقيقة
max: 100, // 100 طلب
message: "تم تجاوز الحد، حاول لاحقاً",
});
app.use("/api", limiter);
5. Middleware للأخطاء
app.use((err, req, res, next) => {
console.error("خطأ:", err.message);
const status = err.status || 500;
res.status(status).json({
error: err.message || "خطأ في السيرفر",
});
});
ترتيب Middleware
⚠️ الترتيب مهم جداً!
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 على مستوى التطبيق
app.use((req, res, next) => {
req.startTime = Date.now();
next();
});
2. Middleware على مستوى Router
const router = express.Router();
router.use((req, res, next) => {
console.log("Router middleware");
next();
});
3. Middleware على مسار محدد
app.get("/admin", authMiddleware, (req, res) => {
res.send("لوحة التحكم");
});
تمارين عملية
تمرين 1: Router بسيط
أنشئ Router للمستخدمين.
الحل:
// 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;
// index.js
app.use("/api/users", require("./routes/users"));
تمرين 2: 3 Routers
أنشئ Routers للمستخدمين والمنتجات والطلبات.
الحل:
app.use("/api/users", require("./routes/users"));
app.use("/api/products", require("./routes/products"));
app.use("/api/orders", require("./routes/orders"));
تمرين 3: Controller
افصل منطق المسار في Controller.
الحل:
// controllers/userController.js
exports.getAll = (req, res) => res.json([]);
// routes/users.js
const ctrl = require("../controllers/userController");
router.get("/", ctrl.getAll);
تمرين 4: Middleware للتسجيل
أضف Middleware يسجّل الوقت.
الحل:
app.use((req, res, next) => {
console.log(new Date().toISOString(), req.method, req.url);
next();
});
تمرين 5: Middleware للمصادقة
أضف Middleware يتحقق من توكن.
الحل:
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 للتحقق
تحقق من بيانات المستخدم.
الحل:
function validate(req, res, next) {
if (!req.body.name) {
return res.status(400).json({ error: "الاسم مطلوب" });
}
next();
}
تمرين 7: 404 Handler
أضف معالج 404.
الحل:
app.use((req, res) => {
res.status(404).json({ error: "غير موجود" });
});
تمرين 8: API كامل
ابنِ API كامل مع Routers و Controllers.
الحل: (راجع المثال الكامل أعلاه)
حل المشاكل الشائعة
🔴 المشكلة 1: Router لا يعمل
السبب: نسيت app.use().
الحل:
app.use("/api/users", usersRouter);
🔴 المشكلة 2: Middleware لا يعمل
السبب: لم تستدعِ next().
الحل:
function middleware(req, res, next) {
// ...
next(); // ← مهم
}
🔴 المشكلة 3: 404 لجميع المسارات
السبب: 404 Handler قبل المسارات.
الحل: ضعه بعد كل المسارات.
🔴 المشكلة 4: Error Handler لا يعمل
السبب: عدد المعاملات خاطئ.
الحل: يجب أن يكون 4 معاملات:
app.use((err, req, res, next) => { ... });
🔴 المشكلة 5: CORS
الحل:
npm install cors
const cors = require("cors");
app.use(cors());
جدول أنواع Middleware
| النوع | الوصف | مثال |
|---|---|---|
| Application | على كل التطبيق | app.use() |
| Router | على Router | router.use() |
| Route | على مسار محدد | app.get(path, mw) |
| Error | معالجة الأخطاء | (err, req, res, next) |
| Built-in | مدمج | express.json() |
| Third-party | خارجي | cors, morgan |
قائمة تحقق نهائية
| المهمة | الحالة |
|---|---|
| فهم Express Router | ⬜ |
| إنشاء Routers منفصلة | ⬜ |
| فصل Controllers عن Routes | ⬜ |
| فهم Middleware | ⬜ |
| Middleware للمصادقة والتحقق | ⬜ |
| ترتيب Middleware الصحيح | ⬜ |
| حل التمارين الثمانية | ⬜ |
ماذا بعد هذا المقال؟
الآن بعد أن أتقنت التوجيه و Middleware، أنت جاهز للمقال التالي:
- بناء REST API — واجهات احترافية.
- قواعد البيانات (MongoDB) — تخزين البيانات.
- المصادقة (JWT) — تسجيل الدخول.
الخلاصة
في هذا المقال، تعلمت:
- ✅ Express Router.
- ✅ تنظيم المشروع (Routes, Controllers).
- ✅ Middleware المتقدم.
- ✅ ترتيب Middleware الصحيح.
- ✅ معالجة الأخطاء.
- ✅ 404 Handler.
- ✅ حل 8 تمارين عملية.
تذكر: التوجيه و Middleware هما ما يجعل تطبيقك منظماً واحترافياً.
مقدمة في Express.js — دليل شامل 2026
بناء REST API في Node.js — دليل شامل 2026
📚 مقالات ذات صلة
مشروع Node.js متكامل — API مع مصادقة JWT 2026
مشروع عملي شامل لبناء API متكامل بـ Node.js و Express و MongoDB — مع مصادقة JWT، رفع الملفات، والنشر
MongoDB مع Node.js — دليل شامل 2026
دليل عملي مفصل لاستخدام MongoDB مع Node.js — Mongoose، Schema، CRUD، العلاقات، مع تمارين وحلول
بناء REST API في Node.js — دليل شامل 2026
دليل عملي مفصل لبناء REST API احترافي — المبادئ، التنظيم، التحقق، والاختبار، مع تمارين وحلول