Middleware nima, qanday ishlaydi, ketma-ketlik muhimligi

~20 daq · Express · Middleware

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:

  1. Middleware ishlaydi — log yozadi
  2. next() chaqiriladi
  3. /users handler ishlaydi
  4. 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