Node.js va Express

Middleware va xatoliklar

Express'ning eng kuchli va o'ziga xos g'oyasi โ€” middleware. So'rov serverga kelgandan javob jo'natilgungacha bo'lgan yo'lda bir necha bosqichdan o'tadi, va har bir bosqich โ€” middleware. Ushbu darsda middleware'larni, ular zanjirini va xatoliklarni to'g'ri boshqarishni o'rganamiz.

Middleware nima?

Middleware โ€” bu so'rov (req) va javob (res) obyektlariga kirish huquqiga ega bo'lgan, so'rovni qayta ishlash zanjiridagi oraliq funksiya. U so'rovni o'zgartirishi, tekshirishi yoki keyingi bosqichga uzatishi mumkin.

Middleware funksiyasi uchta argument oladi:

function mening_middleware(req, res, next) {
  // biror ish qilamiz...
  next(); // keyingi bosqichga o'tkazamiz
}

Middleware ilovaga app.use() bilan qo'shiladi va u har bir so'rovda ishlaydi.

next() va zanjir

Middleware'lar zanjir hosil qiladi. So'rov birinchi middleware'ga kiradi, u next()ni chaqirsa โ€” so'rov keyingisiga o'tadi, va hokazo โ€” oxirida route funksiyasiga yetadi:

const express = require('express');
const app = express();

app.use((req, res, next) => {
  console.log('1-middleware');
  next(); // keyingisiga o't
});

app.use((req, res, next) => {
  console.log('2-middleware');
  next();
});

app.get('/', (req, res) => {
  console.log('Route');
  res.send('Tayyor');
});
// Konsolda: 1-middleware, 2-middleware, Route
Agar middleware'da next()ni chaqirishni unutsangiz va javob ham jo'natmasangiz, so'rov o'sha yerda "osilib" qoladi โ€” brauzer javobni cheksiz kutadi. Har bir middleware yo next()ni chaqirishi, yo javobni jo'natishi shart.
Middleware'lar tartibda ishlaydi โ€” kodda yuqorida yozilgani birinchi ishlaydi. Shuning uchun tartib muhim: masalan, express.json() route'lardan oldin turishi kerak, aks holda route'da req.body bo'sh bo'ladi.

O'rnatilgan middleware: express.json()

Express bir nechta tayyor middleware bilan keladi. Eng muhimi โ€” express.json(). U kiruvchi so'rovning JSON tanasini o'qib, req.bodyga joylaydi:

app.use(express.json());

app.post('/data', (req, res) => {
  console.log(req.body); // JSON tanasi obyekt sifatida
  res.json({ qabul: req.body });
});

Yana bir foydalisi โ€” express.urlencoded(), u HTML formalaridan kelgan ma'lumotni (application/x-www-form-urlencoded) o'qiydi:

app.use(express.urlencoded({ extended: true }));

Statik fayllar: express.static()

Ko'pincha server rasmlar, CSS, HTML va boshqa statik fayllarni ham berishi kerak. express.static() middleware'i ma'lum bir papkadagi fayllarni avtomatik uzatadi:

// 'public' papkasidagi fayllarni uzatish:
app.use(express.static('public'));

// Endi public/rasm.png fayli quyidagi manzilda mavjud:
// http://localhost:3000/rasm.png

Agar public papkasida index.html bo'lsa, u bosh sahifada (/) avtomatik ko'rsatiladi. Bu โ€” statik veb-saytni joylashtirishning eng oson yo'li.

Xavfsizlik uchun mutlaq yo'l berish tavsiya etiladi: app.use(express.static(path.join(__dirname, 'public'))). Bu server qayerdan ishga tushirilishidan qat'i nazar, to'g'ri papkani topadi.

Maxsus middleware: logger

O'z middleware'ingizni yozish oson. Klassik misol โ€” logger: har bir so'rovni konsolga yozib boruvchi middleware. Bu debug qilishda juda foydali:

// Har bir so'rovni vaqti bilan qayd etuvchi logger:
function logger(req, res, next) {
  const vaqt = new Date().toISOString();
  console.log(vaqt + ' - ' + req.method + ' ' + req.url);
  next();
}

app.use(logger);

// Har so'rovda konsolda:
// 2026-07-01T10:00:00.000Z - GET /users

Middleware'lar yordamida autentifikatsiya, ruxsat tekshiruvi, so'rovni tezlikni cheklash (rate limiting) kabi ko'plab vazifalar bajariladi. Ular kodni tartibli va qayta ishlatiladigan qiladi.

// Maxsus middleware'ni faqat bitta route'ga qo'llash mumkin:
function tekshir(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(401).json({ xato: 'Ruxsat yo'q' });
  }
  next();
}

app.get('/maxfiy', tekshir, (req, res) => {
  res.send('Maxfiy ma'lumot');
});

404 โ€” topilmadi

Agar so'rov hech qaysi route'ga mos kelmasa, uni ushlash uchun barcha route'lardan keyin maxsus middleware qo'yiladi. U hech qanday manzil belgilamagani uchun har qanday mos kelmagan so'rovni ushlaydi:

// Barcha route'lardan KEYIN yoziladi:
app.use((req, res) => {
  res.status(404).json({ xato: 'Sahifa topilmadi' });
});
404 middleware'i oxirida turishi shart โ€” barcha route va boshqa middleware'lardan keyin. Agar uni yuqoriga qo'ysangiz, u barcha so'rovlarni ushlab, haqiqiy route'larga yetkazmaydi.

Xatoliklarni boshqarish middleware

Xatoliklarni markazlashgan tarzda boshqarish uchun Express maxsus xato middleware'ini taklif etadi. U oddiy middleware'dan farqli โ€” to'rt argumentni oladi: birinchisi err:

// Xato middleware โ€” DOIM 4 argument!
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ xato: 'Serverda xatolik yuz berdi' });
});

Bu middleware ham barcha route'lardan keyin qo'yiladi. Route ichida xato yuz bersa, uni next(err) orqali shu middleware'ga uzatasiz:

app.get('/xato', (req, res, next) => {
  try {
    // xato bo'lishi mumkin kod...
    throw new Error('Nimadir buzildi');
  } catch (err) {
    next(err); // xato middleware'iga uzatamiz
  }
});
Express funksiyaning to'rt argumentli ekanligiga qarab uni xato middleware sifatida taniydi. Shuning uchun next ishlatilmasa ham, uni to'rtinchi argument sifatida yozish shart: (err, req, res, next).
Middleware'lar tartibi odatda shunday bo'ladi: (1) logger va express.json() kabi umumiy middleware'lar, (2) route'lar, (3) 404 middleware, (4) xato middleware โ€” eng oxirida. Bu tartib so'rovning to'g'ri yo'ldan o'tishini ta'minlaydi.

To'liq misol

Barcha tushunchalarni birlashtiruvchi to'liq server strukturasi:

const express = require('express');
const app = express();

// 1. Umumiy middleware'lar:
app.use(express.json());
app.use((req, res, next) => {
  console.log(req.method + ' ' + req.url);
  next();
});

// 2. Route'lar:
app.get('/', (req, res) => {
  res.send('Bosh sahifa');
});

// 3. 404 (barcha route'lardan keyin):
app.use((req, res) => {
  res.status(404).json({ xato: 'Topilmadi' });
});

// 4. Xato middleware (eng oxirida):
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ xato: 'Server xatosi' });
});

app.listen(3000, () => console.log('Server 3000-portda'));

Xulosa