Node.js va Express

REST API yaratish

Zamonaviy ilovalar aksariyat hollarda REST API orqali muloqot qiladi: mobil ilova, veb-sayt yoki boshqa server serverga so'rov yuboradi va JSON ma'lumot oladi. Ushbu darsda REST tamoyillarini o'rganib, Express'da to'liq ishlaydigan CRUD API yozamiz.

REST nima?

REST (Representational State Transfer) β€” bu API yaratishning uslubi, qoidalar to'plami. Uning asosiy g'oyasi: har bir ma'lumot birligi resurs deb qaraladi va u URL bilan aniqlanadi, resurs ustidagi amallar esa HTTP metodlari bilan bajariladi.

Masalan, "foydalanuvchilar" resursi bilan ishlash:

Diqqat qiling: manzil (URL) o'zgarmaydi (/users), faqat metod o'zgaradi. Bu REST'ning nafisligi β€” manzil nimani, metod esa qanday amalni bildiradi.

CRUD va HTTP metodlari

CRUD β€” ma'lumotlar bilan ishlashning to'rt asosiy amali. Ular HTTP metodlariga to'g'ri keladi:

PUT resursni to'liq almashtiradi, PATCH esa faqat ba'zi maydonlarini yangilaydi. Amaliyotda ko'pincha PUT ishlatiladi, lekin qisman yangilash uchun PATCH to'g'riroq.

Route parametrlari (:id)

Ko'pincha ma'lum bir elementni ID orqali topish kerak bo'ladi. Buning uchun manzilda route parametri β€” ikki nuqta bilan boshlanadigan qism ishlatiladi. Uning qiymati req.paramsda bo'ladi:

app.get('/users/:id', (req, res) => {
  const id = req.params.id;
  res.send('So'ralgan ID: ' + id);
});
// GET /users/42  β†’  So'ralgan ID: 42

Bir necha parametr ham bo'lishi mumkin:

app.get('/users/:userId/posts/:postId', (req, res) => {
  res.json({
    user: req.params.userId,
    post: req.params.postId
  });
});
req.params qiymatlari doim matn (string) bo'ladi. Agar ID son bo'lishi kerak bo'lsa, uni Number(req.params.id) yoki parseInt bilan o'girish kerak β€” aks holda === taqqoslash kutilmagan natija berishi mumkin.

Query parametrlari

URL'ning ?dan keyingi qismi β€” query (so'rov qatori). U odatda filtrlash, saralash, sahifalash uchun ishlatiladi va req.queryda bo'ladi:

app.get('/products', (req, res) => {
  // GET /products?sort=narx&limit=10
  const sort = req.query.sort;   // 'narx'
  const limit = req.query.limit; // '10'
  res.json({ sort, limit });
});
Farqni yodda tuting: route parametri (:id) manzilning majburiy qismi β€” aniq resursni bildiradi. Query (?sort=...) esa ixtiyoriy β€” natijani filtrlash yoki sozlash uchun.

So'rov tanasi (JSON body)

POST va PUT so'rovlarida ma'lumot so'rov tanasida (body) yuboriladi β€” odatda JSON ko'rinishida. Express uni avtomatik o'qimaydi; buning uchun express.json() middleware'ini yoqish kerak:

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

// JSON tanani o'qish uchun (MUHIM!):
app.use(express.json());

app.post('/users', (req, res) => {
  const yangi = req.body; // { ism: 'Ali', yosh: 25 }
  res.json({ qabul_qilindi: yangi });
});
Agar app.use(express.json()) qatorini unutsangiz, req.body undefined bo'ladi. Bu eng ko'p uchraydigan boshlang'ich xatolardan biri! Uni har doim route'lardan oldin qo'shing.

HTTP status kodlar

Har bir javob status kodi bilan keladi β€” u so'rov natijasini bildiradi. To'g'ri status kodlarni qaytarish yaxshi API'ning belgisi:

app.post('/users', (req, res) => {
  if (!req.body.ism) {
    return res.status(400).json({ xato: 'Ism majburiy' });
  }
  // ... yaratish ...
  res.status(201).json({ xabar: 'Yaratildi' });
});

To'liq CRUD API misoli

Endi barchasini birlashtirib, xotirada (massivda) saqlanadigan to'liq CRUD API yozamiz. Bu β€” foydalanuvchilarni boshqaradigan haqiqiy ishlaydigan API:

const express = require('express');
const app = express();
app.use(express.json());

// Ma'lumot β€” oddiy massiv (haqiqiy loyihada bu ma'lumotlar bazasi bo'ladi):
let users = [
  { id: 1, ism: 'Ali', yosh: 25 },
  { id: 2, ism: 'Vali', yosh: 30 }
];
let keyingiId = 3;

// READ: barcha foydalanuvchilar
app.get('/users', (req, res) => {
  res.json(users);
});

// READ: bitta foydalanuvchi
app.get('/users/:id', (req, res) => {
  const id = Number(req.params.id);
  const user = users.find(u => u.id === id);
  if (!user) {
    return res.status(404).json({ xato: 'Topilmadi' });
  }
  res.json(user);
});

Endi yaratish, yangilash va o'chirish amallari:

// CREATE: yangi foydalanuvchi
app.post('/users', (req, res) => {
  const { ism, yosh } = req.body;
  if (!ism) {
    return res.status(400).json({ xato: 'Ism majburiy' });
  }
  const yangi = { id: keyingiId++, ism, yosh };
  users.push(yangi);
  res.status(201).json(yangi);
});

// UPDATE: yangilash
app.put('/users/:id', (req, res) => {
  const id = Number(req.params.id);
  const user = users.find(u => u.id === id);
  if (!user) {
    return res.status(404).json({ xato: 'Topilmadi' });
  }
  user.ism = req.body.ism ?? user.ism;
  user.yosh = req.body.yosh ?? user.yosh;
  res.json(user);
});

// DELETE: o'chirish
app.delete('/users/:id', (req, res) => {
  const id = Number(req.params.id);
  const index = users.findIndex(u => u.id === id);
  if (index === -1) {
    return res.status(404).json({ xato: 'Topilmadi' });
  }
  users.splice(index, 1);
  res.status(204).end();
});

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

Bu API ni sinash uchun brauzerdan faqat GET so'rovlarini yuborish mumkin. POST/PUT/DELETE uchun esa maxsus vositalar β€” Postman, Insomnia yoki terminalda curl ishlatiladi:

# Barcha foydalanuvchilar:
curl http://localhost:3000/users

# Yangi foydalanuvchi yaratish:
curl -X POST http://localhost:3000/users \
  -H 'Content-Type: application/json' \
  -d '{"ism":"Hasan","yosh":22}'

# O'chirish:
curl -X DELETE http://localhost:3000/users/1
Bu misolda ma'lumot massivda saqlanadi, ya'ni server qayta ishga tushganda yo'qoladi. Haqiqiy loyihalarda uning o'rniga ma'lumotlar bazasi (PostgreSQL, MongoDB, MySQL...) ishlatiladi. Lekin route'lar mantiqiy jihatdan aynan shunday qoladi β€” faqat massiv o'rniga baza so'rovlari yoziladi.

Xulosa