REST API — qoidalar, best practices, versiyalash
Muammodan boshlaylik
Jamoada ikki dasturchi. Biri buyurtmalar uchun endpoint yozdi:
POST /getBuyurtma
POST /buyurtmaYaratish
GET /buyurtma/delete?id=5
POST /updateBuyurtma
Ikkinchisi mahsulotlar uchun:
GET /mahsulotlarRoyxati
POST /newMahsulot
GET /mahsulot/5/olib_tashlash
PUT /mahsulot-update
Frontend dasturchi ikkalasini ishlatishi kerak. Har bir endpoint qanday ishlashini alohida o'qishi, eslab qolishi, tushuntirishi kerak. Hamkasbiga yangi endpoint qo'shganda — "bu qanday ishlaydi?" degan savol.
REST — bu muammoning yechimi. Kelishilgan qoidalar bo'lsa — hamma endpoint qanday ishlashini oldindan biladi.
REST nima?
REST (Representational State Transfer) — HTTP API lari uchun arxitektura uslubi. Qat'iy standart emas, balki kelishilgan qoidalar to'plami.
Asosiy g'oya: resurs + HTTP metod
REST da hamma narsa — resurs (buyurtma, foydalanuvchi, mahsulot). HTTP metodlari resurs ustida amal bajaradi.
Resurs HTTP Metod Nima qiladi
─────────────────────────────────────
/users GET Barcha foydalanuvchilar
/users POST Yangi foydalanuvchi yaratish
/users/5 GET ID=5 foydalanuvchi
/users/5 PUT ID=5 ni to'liq yangilash
/users/5 PATCH ID=5 ni qisman yangilash
/users/5 DELETE ID=5 ni o'chirish
Bitta URL, oltita harakat — URL da "nima qilasiz" yozilmaydi.
URL qoidalari
1. Ko'plik ism — resurs nomi
✅ /users ❌ /user
✅ /products ❌ /getProducts
✅ /orders ❌ /orderList
Nima uchun ko'plik? Resurs kolleksiyasi. /users — barcha foydalanuvchilar kolleksiyasi. /users/5 — shu kolleksiyadan bittasi.
2. Kichik harf, tire bilan ajratish
✅ /blog-posts ❌ /blogPosts
✅ /product-reviews ❌ /ProductReviews
✅ /order-items ❌ /order_items
3. Iyerarxiya — ichki resurslar
GET /users/5/orders ← ID=5 foydalanuvchining buyurtmalari
GET /users/5/orders/12 ← shu foydalanuvchining 12-buyurtmasi
POST /users/5/orders ← shu foydalanuvchiga yangi buyurtma
GET /products/3/reviews ← 3-mahsulot sharhlari
POST /products/3/reviews ← 3-mahsulotga yangi sharh
4. Amallar — resurs emas
Ba'zan amal resurs emas — masalan, parol o'zgartirish, to'lov tasdiqlash:
✅ POST /users/5/change-password ← amal nomi tire bilan
✅ POST /orders/12/confirm
✅ POST /payments/3/refund
❌ PUT /users/5?action=changePassword
❌ POST /changePassword
HTTP metodlari to'g'ri ishlatish
const router = require('express').Router();
// GET — faqat o'qish, hech narsa o'zgartirmaslik
router.get('/products', async (req, res) => {
const products = await Product.find();
res.json(products);
});
router.get('/products/:id', async (req, res) => {
const product = await Product.findById(req.params.id);
if (!product) return res.status(404).json({ error: 'Topilmadi' });
res.json(product);
});
// POST — yangi resurs yaratish
router.post('/products', async (req, res) => {
const product = await Product.create(req.body);
res.status(201).json(product); // ← 201 Created
});
// PUT — to'liq yangilash (barcha maydonlar)
router.put('/products/:id', async (req, res) => {
const product = await Product.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, overwrite: true } // ← to'liq almashtirish
);
res.json(product);
});
// PATCH — qisman yangilash (faqat yuborilgan maydonlar)
router.patch('/products/:id', async (req, res) => {
const product = await Product.findByIdAndUpdate(
req.params.id,
{ $set: req.body }, // ← faqat yuborilgan maydonlar
{ new: true }
);
res.json(product);
});
// DELETE — o'chirish
router.delete('/products/:id', async (req, res) => {
await Product.findByIdAndDelete(req.params.id);
res.status(204).send(); // ← 204 No Content
});
PUT va PATCH farqi: PUT — to'liq almashtirish (yuborilmagan maydonlar o'chadi). PATCH — faqat yuborilgan maydonlar yangilanadi. Amalda ko'pincha PATCH ishlatiladi.
HTTP status kodlari
// 2xx — Muvaffaqiyat
res.status(200).json(data); // OK — GET, PUT, PATCH
res.status(201).json(newItem); // Created — POST
res.status(204).send(); // No Content — DELETE
// 4xx — Mijoz xatosi
res.status(400).json({ error: 'Noto\'g\'ri so\'rov' }); // Bad Request
res.status(401).json({ error: 'Autentifikatsiya kerak' }); // Unauthorized
res.status(403).json({ error: 'Ruxsat yo\'q' }); // Forbidden
res.status(404).json({ error: 'Topilmadi' }); // Not Found
res.status(409).json({ error: 'Konflikt (mavjud)' }); // Conflict
res.status(422).json({ error: 'Validatsiya xatosi' }); // Unprocessable
// 5xx — Server xatosi
res.status(500).json({ error: 'Server xatosi' }); // Internal Server Error
res.status(503).json({ error: 'Xizmat vaqtincha to\'xtatilgan' }); // Service Unavailable
401 vs 403 farqi: 401 — kim ekansiz bilmaymiz (login qiling). 403 — kim ekaningizni bilamiz, lekin ruxsat yo'q.
API versiyalash
Vaqt o'tishi bilan API o'zgaradi. Lekin mavjud mijozlar (mobil ilova, boshqa saytlar) eski API dan foydalanmoqda — ularni bir zumda yangilash imkonsiz.
Versiyalash — eski va yangi API bir vaqtda ishlashi uchun:
// URL da versiya (eng keng tarqalgan)
app.use('/api/v1', require('./routes/v1'));
app.use('/api/v2', require('./routes/v2'));
GET /api/v1/users ← eski mijozlar ishlaydi
GET /api/v2/users ← yangi mijozlar yangi formatda
Versiyalar papka tuzilishi
routes/
├── v1/
│ ├── index.js
│ ├── users.js
│ └── products.js
└── v2/
├── index.js
├── users.js ← o'zgargan format
└── products.js
// routes/v1/index.js
const router = require('express').Router();
router.use('/users', require('./users'));
router.use('/products', require('./products'));
module.exports = router;
// routes/v2/index.js — xuddi shunday, lekin v2 modullari
const router = require('express').Router();
router.use('/users', require('./users'));
router.use('/products', require('./products'));
module.exports = router;
Qachon yangi versiya kerak?
Yangi versiya KERAK:
✅ Javob formatini o'zgartirish (maydon nomlarini o'zgartirish)
✅ Majburiy maydonlarni qo'shish
✅ Autentifikatsiya usulini o'zgartirish
Yangi versiya SHART EMAS:
✅ Yangi endpoint qo'shish (mavjud endpointlar saqlanadi)
✅ Ixtiyoriy maydonlar qo'shish
✅ Ichki logikani o'zgartirish (format o'zgarmasa)
To'liq tuzilish misoli
// app.js
const express = require('express');
const app = express();
app.use(express.json());
// Versiyalangan routerlar
app.use('/api/v1', require('./routes/v1'));
// 404 — hech bir route mos kelmasa
app.use((req, res) => {
res.status(404).json({ error: `${req.method} ${req.path} topilmadi` });
});
// Global xato handler
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({ error: 'Serverda xato yuz berdi' });
});
module.exports = app;
// routes/v1/products.js
const router = require('express').Router();
const Product = require('../../models/Product');
const auth = require('../../middleware/auth');
router.get('/', async (req, res, next) => {
try {
const products = await Product.find();
res.json(products);
} catch (err) {
next(err); // ← global handler ga yuborish
}
});
router.post('/', auth, async (req, res, next) => {
try {
const product = await Product.create(req.body);
res.status(201).json(product);
} catch (err) {
next(err);
}
});
module.exports = router;
Tez-tez uchraydigan xatolar
1. GET so'rovda body yuborish
// ❌ — GET body ni qo'llab-quvvatlamaydi (ba'zi mijozlar e'tiborsiz qoldiradi)
app.get('/search', (req, res) => {
const { query } = req.body; // ← ishlamasligi mumkin
});
// ✅ — GET da query params ishlatiladi
app.get('/search', (req, res) => {
const { query } = req.query; // ← /search?query=iphone
});
2. DELETE da 200 qaytarish
// ❌ — o'chirilgan narsaning ma'lumotini qaytarish shart emas
res.status(200).json({ message: 'O\'chirildi', data: deletedItem });
// ✅ — 204 No Content — body bo'lmaydi
res.status(204).send();
Sababi: 204 — "muvaffaqiyatli, lekin javob yo'q" degan standart signal. Frontend bu kodni kutadi va body ni o'qimaydi.
3. Xatoda 200 qaytarish
// ❌ — status 200, lekin aslida xato
res.status(200).json({ success: false, error: 'Topilmadi' });
// ✅ — to'g'ri status kodi
res.status(404).json({ error: 'Topilmadi' });
Sababi: mijoz status kodiga qarab qaror qiladi. 200 kelsa — muvaffaqiyat deb hisoblaydi. Body ni har doim o'qimaydi.
4. Versiyasiz API ni o'zgartirish
❌ — /api/users formatini o'zgartirasiz
Natija: mobil ilova ishlamay qoladi
✅ — /api/v2/users yangi formatda
/api/v1/users eski format saqlanadi
Xulosa
| Qoida | Misol |
|---|---|
| Ko'plik ism | /users, /products |
| HTTP metod = amal | GET o'qish, POST yaratish, DELETE o'chirish |
| To'g'ri status kodi | 201 yaratish, 204 o'chirish, 404 topilmadi |
| Iyerarxiya | /users/5/orders |
| Versiyalash | /api/v1/, /api/v2/ |
REST — kelishuv. Hamma kelishsa — hech kim tushuntirmasdan tushunadi.
Keyingi dars: 37-dars: API Response formatini standartlashtirish