Middleware nima, qanday ishlaydi, ketma-ketlik muhimligi
Muammodan boshlaylik
Sizda 20 ta route bor. Har birida:
- Foydalanuvchi login qilganmi tekshirish kerak
- So'rovni log qilish kerak
- Body ni validate qilish kerak
Buni har bir route da yozish:
app.get('/users', (req, res) => {
// login tekshirish...
// log yozish...
// validate...
// asosiy ish
});
app.get('/products', (req, res) => {
// login tekshirish... (takror)
// log yozish... (takror)
// validate... (takror)
// asosiy ish
});
// ... 18 ta route yana
Bu — kod takrorlanishi. Bir joyni o'zgartirsangiz — 20 ta joyni o'zgartirish kerak.
Middleware bu muammoni hal qiladi.
Middleware nima?
Middleware — so'rov va javob o'rtasida ishlaydigan funksiya. So'rov keladi, middleware ni o'tadi, keyin handler ga yetadi.
Hayotiy o'xshatma: siz aeroportga keldingiz. Samolyotga chiqishdan oldin bir nechta tekshiruvdan o'tasiz: bilet tekshirish → pasport tekshirish → xavfsizlik tekshiruvi → boarding. Har bir tekshiruv — middleware. Hammasi o'tsa — samolyotga chiqasiz (handler). Bittasi to'xtatsa — chiqmaysiz.
So'rov → [middleware 1] → [middleware 2] → [middleware 3] → Handler → Javob
Middleware qanday ko'rinadi?
Middleware — uch argument oluvchi funksiya: req, res, next.
function myMiddleware(req, res, next) {
console.log('So\'rov keldi:', req.method, req.url);
next(); // keyingi middleware yoki handler ga o'tish
}
next() — "men ishimni qildim, keyingisi ishlaydi" degani. next() chaqirilmasa — so'rov shu yerda qotib qoladi, javob hech qachon yuborilmaydi.
app.use() — middleware qo'shish
const express = require('express');
const app = express();
// Barcha so'rovlar uchun:
app.use((req, res, next) => {
console.log(`${req.method} ${req.url} — ${new Date().toISOString()}`);
next();
});
app.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Ali' }]);
});
app.listen(3000);
/users ga so'rov kelganda:
- Middleware ishlaydi — log yozadi
next()chaqiriladi/usershandler ishlaydi- Javob yuboriladi
Ketma-ketlik — eng muhim qoida
Middleware lar yozilgan tartibda ishlaydi. Bu — Express ning asosiy qoidasi.
app.use(middlewareA); // birinchi
app.use(middlewareB); // ikkinchi
app.use(middlewareC); // uchinchi
app.get('/users', handler);
So'rov kelganda: A → B → C → handler.
Tartib noto'g'ri bo'lsa:
app.get('/users', handler); // handler avval
app.use((req, res, next) => {
req.user = { id: 1 }; // bu handler dan keyin — hech qachon ishlamaydi
next();
});
/users ga so'rov kelganda — handler darhol ishlaydi, middleware hech qachon chaqirilmaydi.
next() ni chaqirmaslik — to'xtatish
Middleware next() chaqirmasa — so'rov shu yerda to'xtaydi. Bu autentifikatsiya uchun ishlatiladi:
function authMiddleware(req, res, next) {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: 'Token kerak' });
// next() chaqirilmadi — handler ga yetmaydi
}
req.user = { id: 1, name: 'Ali' }; // req ga ma'lumot qo'shish
next(); // token bor — davom etish
}
app.get('/profile', authMiddleware, (req, res) => {
res.json(req.user); // middleware qo'shgan ma'lumot
});
Middleware turlari
Global middleware — barcha so'rovlarga:
app.use(express.json()); // barcha so'rovlar uchun body parse
app.use(loggerMiddleware); // barcha so'rovlar uchun log
Route middleware — faqat ma'lum route uchun:
app.get('/profile', authMiddleware, (req, res) => {
res.json(req.user);
});
Router middleware — faqat ma'lum prefix uchun:
app.use('/api', apiMiddleware); // faqat /api/... so'rovlari uchun
req ga ma'lumot qo'shish
Middleware req ob'ektiga yangi xususiyat qo'sha oladi — keyingi middleware va handler lar uni ko'radi:
// Middleware:
app.use((req, res, next) => {
req.requestTime = Date.now();
req.requestId = Math.random().toString(36).slice(2);
next();
});
// Handler:
app.get('/users', (req, res) => {
console.log('So\'rov vaqti:', req.requestTime);
console.log('So\'rov ID:', req.requestId);
res.json({ users: [] });
});
Bu pattern — autentifikatsiya middleware da req.user qo'shish uchun keng ishlatiladi.
Amaliy misol — bir nechta middleware zanjiri
const express = require('express');
const app = express();
app.use(express.json());
// 1. Logger
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
// 2. Request ID
app.use((req, res, next) => {
req.id = Math.random().toString(36).slice(2, 9);
res.set('X-Request-Id', req.id);
next();
});
// 3. Auth (faqat /api/* uchun)
app.use('/api', (req, res, next) => {
const token = req.headers['authorization'];
if (!token) return res.status(401).json({ error: 'Token kerak' });
req.user = { id: 1 }; // token tekshirildi (soddalashtirilgan)
next();
});
// Handler
app.get('/api/profile', (req, res) => {
res.json({ user: req.user, requestId: req.id });
});
app.get('/health', (req, res) => {
res.json({ status: 'ok' }); // auth kerak emas
});
app.listen(3000);
/api/profile so'rovi: Logger → RequestId → Auth → Handler
/health so'rovi: Logger → RequestId → Handler (Auth o'tkazib yuboriladi)
Tez-tez uchraydigan xatolar
next() unutish:
app.use((req, res, next) => {
console.log('So\'rov keldi');
// next() yo'q — so'rov qotib qoladi, javob hech qachon kelmaydi
});
Middleware ni route dan keyin qo'yish:
app.get('/users', handler);
app.use(authMiddleware); // kech — /users ga ta'sir qilmaydi
next() dan keyin res ga yozish:
app.use((req, res, next) => {
next();
res.json({ extra: 'data' }); // Xato! Javob allaqachon yuborilgan bo'lishi mumkin
});
next() chaqirilgandan keyin res ga tegmaslik kerak.
Xulosa
Middleware — so'rov va javob o'rtasida ishlaydigan funksiya. req, res, next oladi. next() chaqirilsa — keyingisi ishlaydi. Chaqirilmasa — to'xtaydi.
Ketma-ketlik muhim — middleware lar yozilgan tartibda ishlaydi. Global middleware lar route lardan oldin yoziladi.
req ga ma'lumot qo'shish — keyingi middleware va handler lar uchun ma'lumot uzatish usuli.
Keyingi dars
8-dars: Built-in Middleware — express.json, express.urlencoded