5.7-bob: REST API dizayni (resurslar, metodlar, status, versiyalash, best practices)
5-QISM — Node.js Backend · 7-mavzu
1. Kirish va motivatsiya
5.5–5.6-boblarda API qanday yozishni (http, Express) o'rgandik. Endi undan ham muhimrog'ini — API'ni qanday dizayn qilishni — o'rganamiz. Ikki dasturchi bir xil funksiyani beradigan API yozishi mumkin, lekin biri toza, bashoratli, kengaytiriladigan, ikkinchisi — chalkash, mo'rt, ishlatib bo'lmaydigan. Farq — dizaynda.
REST (Representational State Transfer) — Roy Fielding (2000) tomonidan ta'riflangan, web API'lar uchun arxitektura uslubi. Bu — qoidalar to'plami emas, balki prinsiplar: resurslarni qanday nomlash, HTTP metodlarini qanday ishlatish, status kodlarni qanday tanlash, javoblarni qanday tuzish. Yaxshi REST API — uni ishlatuvchi (frontend, mobil, boshqa servis) hujjatsiz ham taxmin qila oladigan API.
O'xshatish: REST — yaxshi kutubxona kataloglash tizimi. Har kitob (resurs) mantiqiy joyda (
/books/42); kitobni olish (GET), qo'shish (POST), o'chirish (DELETE) — aniq qoidalar. Yangi kutubxonachi (dasturchi) tizimni bir qarashda tushunadi. Yomon API — kitoblar tasodifiy joyda, har biriga boshqacha murojaat — chalkashlik.
Nega muhim?
- Frontendbackend shartnomasi — API dizayni ikki jamoa kelishuvi (11, 12).
- Bashoratlilik — yaxshi API'ni ishlatuvchi hujjatsiz taxmin qiladi.
- Kengaytiriladigan — versiyalash, sahifalash — o'sishga tayyor.
- Professional belgi — yomon API'ni keyin tuzatish qimmat; yaxshi dizayn boshidan.
2. Nazariya — chuqur tushuntirish
2.1. REST nima va 6 cheklov (constraints)
REST — arxitektura uslubi; 6 prinsip (constraint) ga asoslanadi (Fielding):
- Client-Server — frontend va backend ajratilgan 0.4-bob; mustaqil rivojlanadi.
- Stateless — har so'rov o'zini-o'zi ta'minlaydi; server so'rovlar orasida holat saqlamaydi (2.7-JS: HTTP stateless).
- Cacheable — javoblar keshlanadigan bo'lishi mumkin (0.1, 2.14).
- Uniform Interface — bir xil, izchil interfeys (resurs, metod, status) — REST yuragi.
- Layered System — qatlamlar (load balancer, cache, API gateway — 9.8) — client bilmaydi.
- Code on Demand (ixtiyoriy) — server client'ga kod yuborishi mumkin (kam).
Eng muhim: uniform interface (izchil) + stateless. Bular API'ni bashoratli va masshtablanadigan 9.9-bob qiladi.
2.2. Resource-oriented dizayn (resurs — REST markazi)
REST'da hamma narsa — resurs (ot/narsa): foydalanuvchi, mahsulot, buyurtma. URL — resursni identifikatsiya qiladi; HTTP metod — unga amalni (Microsoft, Stack Overflow):
FE'L (action) URL'da: OT (resurs) URL'da:
/getUsers GET /users
/createUser POST /users
/deleteUser?id=5 DELETE /users/5
/updateUserName PATCH /users/5Asosiy qoida: URL — ot (resurs); HTTP metod — fe'l (amal).
/getUsersemas,GET /users. Amal metodda, resursda emas (Stack Overflow).
2.3. Resurs nomlash konvensiyalari
Ko'plik ot: /users (collection), /users/5 (bitta)
Iyerarxiya: /users/5/orders (5-foydalanuvchining buyurtmalari)
Kichik harf, tire: /blog-posts (camelCase/underscore emas)
Versiya: /api/v1/users (2.10)
Fe'l: /getUsers, /createOrder
Birlik collection: /user (ko'plik: /users)
Kengaytma: /users.json (Accept header — 2.13)2.4. HTTP metodlar va CRUD (0.4 amaliyoti)
Har CRUD amali — HTTP metod (Microsoft, 0.4):
| Metod | CRUD | Misol | Safe? | Idempotent? |
|---|---|---|---|---|
| GET | Read | GET /users, GET /users/5 |
||
| POST | Create | POST /users |
||
| PUT | Replace (to'liq) | PUT /users/5 |
||
| PATCH | Update (qisman) | PATCH /users/5 |
~ | |
| DELETE | Delete | DELETE /users/5 |
- Safe — server holatini o'zgartirmaydi (GET — faqat o'qish; brauzer/proxy keshlaydi — 0.4).
- Idempotent — bir necha marta chaqirsa ham bir xil natija 2.9-bob.
2.5. PUT vs PATCH (eng ko'p chalkashlik)
PUT /users/5 — TO'LIQ almashtirish (butun obyektni yuborasiz)
body: { ism: "Ali", email: "a@b.uz", yosh: 20 } HAMMA maydon
yo'q maydonlar O'CHADI (yoki default)
PATCH /users/5 — QISMAN yangilash (faqat o'zgaradigan)
body: { yosh: 21 } faqat yosh
boshqa maydonlar O'ZGARMAYDIQaysi: PATCH — kundalik (faqat o'zgargan maydon — kam ma'lumot, xavfsizroq). PUT — to'liq almashtirish kerak bo'lganda. Ko'p API faqat PATCH ishlatadi.
2.6. Status kodlar — to'g'ri tanlash (0.4 chuqur)
To'g'ri status kod — API'ning "tili" (0.4: 2xx/3xx/4xx/5xx):
| Kod | Qachon |
|---|---|
200 OK |
muvaffaqiyatli GET/PATCH/PUT (ma'lumot bilan) |
201 Created |
POST muvaffaqiyatli (yangi resurs yaratildi) |
204 No Content |
DELETE muvaffaqiyatli (javob body'siz) |
400 Bad Request |
noto'g'ri so'rov (validatsiya — 5.9) |
401 Unauthorized |
autentifikatsiya yo'q/noto'g'ri (5.15) |
403 Forbidden |
autentifikatsiya bor, lekin ruxsat yo'q (RBAC — 5.17) |
404 Not Found |
resurs topilmadi |
409 Conflict |
ziddiyat (masalan email band) |
422 Unprocessable Entity |
validatsiya xatosi (semantik) |
429 Too Many Requests |
rate limit (5.20) |
500 Internal Server Error |
server xatosi (kod buzildi) |
401 vs 403: 401 — "kim ekaningni bilmayman" (login kerak — 5.15). 403 — "kim ekaningni bilaman, lekin ruxsating yo'q" (admin emas — 5.17). Bu farqni chalkashtirmang.
2.7. Query parametrlar: filtr, sort, sahifalash (Stack Overflow)
Filtrlash, saralash, sahifalash — query stringda (path'da emas — 2.3):
Filtr: GET /users?role=admin&active=true
Saralash: GET /products?sort=-price (- = kamayish), ?sort=name
Sahifalash: GET /posts?page=2&limit=20 (yoki ?offset=20&limit=20)
Maydon tanlash: GET /users?fields=id,ism (faqat kerakli maydonlar)
Qidiruv: GET /products?search=telefon2.8. Sahifalash (pagination) — chuqur
Katta to'plamni bo'lak-bo'lak qaytarish (0.1: xotira; 3.1: performance) (Microsoft):
Offset-based: ?page=2&limit=20 (20–39 yozuvlar) — oddiy, lekin katta offsetda sekin
Cursor-based: ?cursor=abc123&limit=20 — tez, real-time uchun (oxirgi ID'dan)Javobda meta ma'lumot beriladi (jami, sahifa, keyingi bormi):
{
"data": [ ... ],
"meta": { "page": 2, "limit": 20, "total": 145, "totalPages": 8 }
}2.9. Idempotency (qayta chaqirish xavfsizligi)
Idempotent — bir necha marta chaqirsa ham bir xil natija (qo'shimcha ta'sirsiz — 2.4). Nega muhim: tarmoq uzilsa 0.4-bob, client qayta urinadi — duplikat yaratilmasligi kerak:
GET /users/5 — 100 marta chaqiring bir xil (idempotent )
DELETE /users/5 — 2-marta allaqachon yo'q (idempotent , 204 yoki 404)
PUT /users/5 — 2-marta bir xil holat (idempotent )
POST /users — 2-marta IKKI user! (idempotent EMAS )POST idempotent emas — qayta yuborilsa duplikat. Yechim: idempotency key (client noyob kalit yuboradi; server takrorni aniqlaydi) — to'lov API'larida muhim.
2.10. Versiyalash (API o'zgarganda)
API o'zgarsa, eski client'lar buzilmasligi uchun versiyalash (Microsoft):
1. URL path (eng keng tarqalgan): /api/v1/users, /api/v2/users
2. Header: Accept: application/vnd.api.v1+json
3. Query: /users?version=1URL path versiyalash (
/api/v1/) — eng oddiy, ko'rinadigan, ko'p ishlatiladi. Breaking change (4.5: MAJOR — semver 0.7) bo'lsa,/v2chiqariladi;/v1qo'llab-quvvatlanadi (eski client buzilmaydi).
2.11. Izchil javob shakli (consistent response)
Barcha javoblar bir xil shaklda bo'lsin — client bashorat qiladi:
// Muvaffaqiyat
{ "success": true, "data": { ... } }
// Ro'yxat (meta bilan — 2.8)
{ "success": true, "data": [ ... ], "meta": { ... } }
// Xato (2.12)
{ "success": false, "error": { "code": "NOT_FOUND", "message": "..." } }Izchillik — frontend (11) uchun katta yengillik: har endpoint javobini
res.data.datadeb o'qiydi, har xil shaklni o'rganmaydi.
2.12. Xato javoblar formati
Xatolar ham izchil va foydali bo'lsin (5.10 ga ko'prik):
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Ma'lumot noto'g'ri",
"details": [
{ "field": "email", "message": "Email noto'g'ri" }
]
}
}Yomon:
500+ HTML xato sahifasi, yoki har xil shakl. Yaxshi: to'g'ri status 2.6-bob + izchil JSON + tushunarli xabar (texnik tafsilot log'da — 5.12, foydalanuvchiga emas — 14).
2.13. Content negotiation va HTTP semantikasi
Content-Type(so'rov) — client nima yuboryapti (application/json).Accept(so'rov) — client nima kutadi (application/json).Content-Type(javob) — server nima qaytaryapti.
REST API odatda JSON 0.4-bob; Content-Type: application/json doim.
2.14. Caching (ETag, Cache-Control)
Cacheable 2.1-bob — javoblarni keshlash (0.1, performance):
Cache-Control: max-age=3600 — 1 soat keshlansin 0.4-bob
ETag: "abc123" — resurs versiyasi (o'zgarmagan bo'lsa 304 — 0.4)
If-None-Match: "abc123" — client: shu versiyam bor; o'zgardimi?
304 Not Modified (o'zgarmagan — body yubormaydi, tejaydi)2.15. HATEOAS (ilg'or — ixtiyoriy)
HATEOAS (Hypermedia as the Engine of Application State) — javobda keyingi mumkin amallar havolalari beriladi:
{
"data": { "id": 5, "ism": "Ali" },
"links": { "self": "/users/5", "orders": "/users/5/orders" }
}HATEOAS — "to'liq REST" (Richardson Maturity Model 3-daraja), lekin amalda kam ishlatiladi (murakkab). Ko'p API undan voz kechadi. G'oyani bilish kifoya.
2.16. RESTful bo'lmagan holatlar (amal-asoslangan)
Hamma narsa CRUD'ga to'g'ri kelmaydi. Murakkab amallar uchun fe'l-resurs maqbul:
POST /users/5/activate — aktivlashtirish (CRUD emas)
POST /orders/5/cancel — bekor qilish
POST /auth/login — login 5.15-bob
POST /payments/5/refund — qaytarishPragmatik bo'ling: REST — qoida emas, yo'riqnoma. 95% resurs-asoslangan; murakkab amal uchun fe'l ishlatish — normal.
2.17. API hujjatlash va xavfsizlik (pointerlar)
- Hujjatlash: Swagger/OpenAPI 5.23-bob — API'ni avtomatik hujjatlaydi.
- Xavfsizlik: HTTPS (0.4, 14), auth 5.15-bob, rate limit 5.20-bob, CORS 5.20-bob, validatsiya 5.9-bob.
- Versiyalash + deprecation: eski versiyani ogohlantirib (header), keyin o'chirish.
3. Sintaksis — REST dizayn yo'riqnomasi
RESURS: ot, ko'plik — /users, /users/5, /users/5/orders
METOD: GET (o'qish), POST (yaratish201), PUT (to'liq), PATCH (qisman), DELETE (204)
STATUS: 200/201/204 | 400/401/403/404/409/422/429 (client) | 500 (server)
QUERY: ?role=admin (filtr) &sort=-price &page=2&limit=20 (2.7, 2.8)
VERSIYA: /api/v1/... 2.10-bob
JAVOB: { success, data, meta } / { success:false, error } (2.11, 2.12)4. Batafsil kod namunalari (Express bilan — 5.6)
Misol 1 — RESTful resurs route'lari (2.2, 2.4)
import { Router } from "express"; // (5.6)
const router = Router();
// Resurs: users (ot, ko'plik — 2.3)
router.get("/", getAllUsers); // GET /users — ro'yxat
router.get("/:id", getUser); // GET /users/5 — bitta
router.post("/", createUser); // POST /users — yaratish (201)
router.patch("/:id", updateUser); // PATCH /users/5 — qisman (2.5)
router.delete("/:id", deleteUser); // DELETE /users/5 — o'chirish (204)
// Iyerarxik resurs (2.3)
router.get("/:id/orders", getUserOrders); // GET /users/5/orders
export default router;
// app.use("/api/v1/users", router) versiya bilan (2.10)Misol 2 — To'g'ri status kodlar (2.6)
// GET — 200 yoki 404
const getUser = (req, res) => {
const user = users.find(u => u.id === Number(req.params.id)); // (5.6)
if (!user) {
return res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Foydalanuvchi topilmadi" } }); // (2.6, 2.12)
}
res.status(200).json({ success: true, data: user }); // (2.11)
};
// POST — 201 Created
const createUser = (req, res) => {
const yangi = { id: nextId++, ...req.body };
users.push(yangi);
res.status(201).json({ success: true, data: yangi }); // 201! (2.6)
};
// DELETE — 204 No Content
const deleteUser = (req, res) => {
users = users.filter(u => u.id !== Number(req.params.id));
res.status(204).end(); // body'siz (2.6)
};Misol 3 — Sahifalash (pagination — 2.8)
const getAllUsers = (req, res) => {
const page = Math.max(1, Number(req.query.page) || 1); // (5.6: query)
const limit = Math.min(100, Number(req.query.limit) || 20); // max 100 (DoS — 14)
const offset = (page - 1) * limit;
const sahifaData = users.slice(offset, offset + limit); // (2.7-JS: slice)
const total = users.length;
res.json({
success: true,
data: sahifaData,
meta: { // (2.8)
page, limit, total,
totalPages: Math.ceil(total / limit),
hasNext: offset + limit < total,
}
});
};
// GET /users?page=2&limit=20Misol 4 — Filtr va saralash (2.7)
const getProducts = (req, res) => {
let natija = [...products]; // nusxa (2.7-JS)
// Filtr (2.7)
const { category, minPrice, inStock } = req.query;
if (category) natija = natija.filter(p => p.category === category);
if (minPrice) natija = natija.filter(p => p.price >= Number(minPrice));
if (inStock === "true") natija = natija.filter(p => p.stock > 0);
// Saralash 2.7-bob: ?sort=-price (kamayish), ?sort=name (o'sish)
const sort = req.query.sort;
if (sort) {
const desc = sort.startsWith("-"); // (2.6-JS)
const maydon = desc ? sort.slice(1) : sort;
natija.sort((a, b) => desc ? b[maydon] - a[maydon] : a[maydon] - b[maydon]); // (3.9)
}
res.json({ success: true, data: natija });
};
// GET /products?category=phone&minPrice=100&sort=-priceMisol 5 — PUT vs PATCH (2.5)
// PUT — TO'LIQ almashtirish (barcha maydon kerak — 2.5)
const replaceUser = (req, res) => {
const idx = users.findIndex(u => u.id === Number(req.params.id));
if (idx === -1) return res.status(404).json({ success: false, error: { message: "Topilmadi" } });
const { ism, email, yosh } = req.body; // hamma maydon
if (!ism || !email) return res.status(400).json({ success: false, error: { message: "Barcha maydon kerak" } });
users[idx] = { id: users[idx].id, ism, email, yosh }; // TO'LIQ almashtir
res.json({ success: true, data: users[idx] });
};
// PATCH — QISMAN (faqat berilgan maydonlar — 2.5)
const updateUser = (req, res) => {
const user = users.find(u => u.id === Number(req.params.id));
if (!user) return res.status(404).json({ success: false, error: { message: "Topilmadi" } });
Object.assign(user, req.body); // faqat berilganlar (2.8-JS)
res.json({ success: true, data: user });
};Misol 6 — Versiyalash (URL path — 2.10)
import express from "express";
import usersV1 from "./routes/v1/users.js";
import usersV2 from "./routes/v2/users.js";
const app = express();
app.use(express.json()); // (5.6)
app.use("/api/v1/users", usersV1); // eski (qo'llab-quvvatlanadi)
app.use("/api/v2/users", usersV2); // yangi (breaking change — 4.5)
// v1 client'lar buzilmaydi; yangi client'lar v2 (2.10)Misol 7 — Izchil javob va xato (helper — 2.11, 2.12)
// Javob helper'lari (izchillik — 2.11)
const ok = (res, data, status = 200) => res.status(status).json({ success: true, data });
const fail = (res, status, code, message, details) =>
res.status(status).json({ success: false, error: { code, message, ...(details && { details }) } });
// Ishlatish
const getUser = (req, res) => {
const user = users.find(u => u.id === Number(req.params.id));
if (!user) return fail(res, 404, "NOT_FOUND", "Foydalanuvchi topilmadi"); // (2.12)
ok(res, user); // (2.11)
};
const createUser = (req, res) => {
if (!req.body.email) return fail(res, 400, "VALIDATION", "Email kerak");
const yangi = { id: nextId++, ...req.body };
users.push(yangi);
ok(res, yangi, 201); // 201
};Misol 8 — Nested resurs va amal-asoslangan (2.3, 2.16)
// Iyerarxik: foydalanuvchining buyurtmalari (2.3)
router.get("/users/:userId/orders", (req, res) => {
const orders = barchaBuyurtmalar.filter(o => o.userId === Number(req.params.userId));
res.json({ success: true, data: orders });
});
// Amal-asoslangan (CRUD emas — 2.16)
router.post("/orders/:id/cancel", (req, res) => { // bekor qilish
const order = topBuyurtma(req.params.id);
if (order.status === "shipped") {
return res.status(409).json({ success: false, error: { message: "Yuborilgan buyurtma bekor qilinmaydi" } }); // 409 Conflict (2.6)
}
order.status = "cancelled";
res.json({ success: true, data: order });
});Misol 9 — Caching (ETag — 2.14)
import crypto from "node:crypto"; // (5.3)
const getUser = (req, res) => {
const user = users.find(u => u.id === Number(req.params.id));
if (!user) return res.status(404).end();
const etag = crypto.createHash("md5").update(JSON.stringify(user)).digest("hex"); // (5.3: hash)
res.set("ETag", etag); // (2.14)
if (req.headers["if-none-match"] === etag) { // o'zgarmagan?
return res.status(304).end(); // 304 — body yo'q (tejaydi — 0.4)
}
res.json({ success: true, data: user });
};Misol 10 — To'liq RESTful controller (best practices birga)
// controllers/productController.js (5.6: qatlamli)
const products = [];
let nextId = 1;
// GET /products — filtr + sort + pagination (2.7, 2.8)
export const list = (req, res) => {
let natija = [...products];
if (req.query.category) natija = natija.filter(p => p.category === req.query.category);
if (req.query.sort) {
const desc = req.query.sort.startsWith("-");
const m = desc ? req.query.sort.slice(1) : req.query.sort;
natija.sort((a, b) => (desc ? b[m] - a[m] : a[m] - b[m]));
}
const page = Number(req.query.page) || 1, limit = Math.min(100, Number(req.query.limit) || 20);
const data = natija.slice((page - 1) * limit, page * limit);
res.json({ success: true, data, meta: { page, limit, total: natija.length } });
};
// GET /products/:id (2.6)
export const getOne = (req, res) => {
const p = products.find(x => x.id === Number(req.params.id));
if (!p) return res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Topilmadi" } });
res.json({ success: true, data: p });
};
// POST /products (2.6: 201)
export const create = (req, res) => {
const { nom, price } = req.body;
if (!nom || price == null) return res.status(400).json({ success: false, error: { code: "VALIDATION", message: "nom va price kerak" } });
const yangi = { id: nextId++, nom, price, createdAt: new Date().toISOString() };
products.push(yangi);
res.status(201).json({ success: true, data: yangi });
};5. To'g'ri va noto'g'ri holatlar
1) Fe'l URL'da (resurs o'rniga)
POST /createUser, GET /getUserById?id=5
POST /users, GET /users/5 (metod fe'l, URL ot — 2.2)2) Noto'g'ri status kod
// hammasi 200 (xato ham 200 bilan)
res.json({ error: "topilmadi" }); // status 200!
// to'g'ri status (2.6)
res.status(404).json({ success: false, error: {...} });3) Filtr/sahifalashni path'da
/users/admin/page/2 (path'da filtr)
/users?role=admin&page=2 (query'da — 2.7)4) Izchil bo'lmagan javob shakli
// har endpoint har xil shakl (frontend qiynaladi)
res.json(users); // bir joyda massiv
res.json({ result: user }); // boshqa joyda obyekt
// izchil (2.11)
res.json({ success: true, data: ... });5) Versiyasiz API (keyin breaking change)
/api/users (versiyasiz) o'zgarish eski client'larni buzadi
/api/v1/users 2.10-bob v2 chiqarib, v1 saqlanadi6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Frontend "qaysi maydonni o'qiyman?" deb chalkashadi
Sababi: izchil bo'lmagan javob shakli 2.11-bob. Yechimi: har javob { success, data }; helper (Misol 7).
Xato 2 — Xatoda 200 status (frontend xatoni sezmaydi)
Sababi: noto'g'ri status 2.6-bob. Yechimi: to'g'ri 4xx/5xx; res.status(...).
Xato 3 — Katta to'plam sekin/xotira to'ladi
Sababi: sahifalashsiz hamma yozuv (0.1, 2.8). Yechimi: pagination (limit majburiy, max chegara — Misol 3).
Xato 4 — POST qayta yuborilib, duplikat
Sababi: POST idempotent emas 2.9-bob. Yechimi: idempotency key; yoki unique constraint (DB — 6).
Xato 5 — API o'zgarib, mobil ilova buzildi
Sababi: versiyasiz breaking change 2.10-bob. Yechimi: versiyalash; eski versiyani saqlash.
Xato 6 — Maxfiy ma'lumot javobda (parol hash)
Sababi: butun obyektni qaytarish (14). Yechimi: faqat kerakli maydonlar (fields yoki controller'da tanlash — passwordni olib tashlang).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Express 5.6-bob: REST'ning amaliy bajarilishi.
- HTTP 0.4-bob: metod, status, header — REST'ning quroli.
- Validatsiya 5.9-bob: 400/422; xato formati.
- Error handling 5.10-bob: izchil xato javobi.
- Auth (5.15, 5.17): 401/403;
/auth/login. - Swagger 5.23-bob: REST API'ni hujjatlash.
- Frontend (11, 12): API'ni iste'mol qilish — izchil shakl yengillashtiradi.
- NestJS (8): REST + dekoratorlar (
@Get,@Post).
8. Eng yaxshi amaliyotlar (best practices)
- URL — ot (resurs, ko'plik); metod — fe'l (
GET /users— 2.2, 2.3). - To'g'ri status kodlar (201 Create, 204 Delete, 404, 400 — 2.6); 401 vs 403 farqi.
- Filtr/sort/pagination — query'da 2.7-bob; pagination'da
limitchegarasi (DoS — 14). - Izchil javob shakli (
{ success, data, meta }) + xato ({ error }) — helper bilan (2.11, 2.12). - Versiyalash (
/api/v1/) — breaking change uchun (2.10, 4.5). - PATCH (qisman) — kundalik; PUT — to'liq 2.5-bob.
- Stateless — har so'rov o'zini ta'minlaydi (token — 5.15); server session'ga bog'lanmaydi 2.1-bob.
- Maxfiy ma'lumotni qaytarmang (parol hash — 14); faqat kerakli maydonlar.
- Pragmatik REST — murakkab amalga fe'l-resurs 2.16-bob; HATEOAS shart emas.
- Hujjatla (Swagger — 5.23); HTTPS + auth + rate limit (14).
9. Amaliy loyiha: "Professional RESTful API Dizayni"
REST prinsiplarini amalda mustahkamlash — to'liq, professional API.
Maqsad
Resurs-asoslangan dizayn, to'g'ri metod/status, sahifalash, filtr, versiyalash va izchil javob/xato formatini birlashtirib, professional REST API qurish.
Talablar (requirements)
- Kamida 2 resurs (masalan
products,orders) — RESTful route'lar (ot, ko'plik,express.Router— 5.6, 2.2). - To'liq CRUD: GET (ro'yxat + bitta), POST (201), PATCH (qisman), PUT (to'liq), DELETE (204) — to'g'ri status (2.4, 2.6).
- Sahifalash:
?page=&limit=+ meta (total/totalPages/hasNext);limitmax chegara (Misol 3, 2.8). - Filtr + saralash:
?category=&minPrice=&sort=-price(Misol 4, 2.7). - Izchil javob:
{ success, data, meta }/{ success:false, error }— helper bilan (Misol 7, 2.11, 2.12). - Versiyalash:
/api/v1/...2.10-bob. - Iyerarxik resurs:
/products/:id/reviewsyoki/users/:id/orders(2.3, Misol 8). - Amal-asoslangan endpoint:
POST /orders/:id/cancel— 409 holati bilan (2.16, Misol 8). - To'g'ri xato status: 400/404/409; maxfiy ma'lumotni qaytarmang (2.6, 6-xato).
- (Bonus) ETag bilan caching (Misol 9, 2.14).
Maslahatlar (hint)
- URL — ot, metod — fe'l 2.2-bob;
express.Router5.6-bob. - Status: POST201, DELETE204, topilmadi404 2.6-bob.
- Pagination:
slice((page-1)*limit, page*limit)+ meta (Misol 3). - Filtr/sort: query'dan o'qib,
filter/sort(3.9, Misol 4). - Javob helper:
ok(res, data)/fail(res, status, code, msg)(Misol 7). limitni max chegarala (DoS — 14).
"Tayyor" mezonlari (acceptance criteria)
- Resurslar ot/ko'plik, RESTful route'lar.
- To'liq CRUD to'g'ri metod/status bilan (201/204/404/400).
- Sahifalash meta bilan; limit cheklangan.
- Filtr va saralash query orqali.
- Izchil javob/xato shakli (helper).
- Versiyalash (
/api/v1/). - Iyerarxik va amal-asoslangan endpoint.
- Maxfiy ma'lumot qaytarilmaydi; to'g'ri status kodlar.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda REST API dizaynini professional darajada o'rgandik:
- REST — arxitektura uslubi (6 cheklov: client-server, stateless, cacheable, uniform interface, layered).
- Resurs-asoslangan: URL — ot/ko'plik (
/users/5); metod — fe'l (GET/POST/PUT/PATCH/DELETE — CRUD). - Status kodlar (201/204/400/401/403/404/409/422/429/500); 401 vs 403.
- Query: filtr/sort/pagination (meta bilan); PUT (to'liq) vs PATCH (qisman).
- Versiyalash (
/api/v1/); idempotency (POST emas); izchil javob/xato shakli. - Caching (ETag/Cache-Control); pragmatik REST (amal-asoslangan — 2.16).
Keyingi bob — 5.8-bob: Environment variables — dotenv, config. API yozishni va dizaynni bildik; endi uni sozlashni — maxfiy ma'lumot (DB parol, API kalit, port) ni koddan ajratib, environment variables (.env — 4.5) va config tizimini o'rganamiz. Bu — xavfsizlik (14) va turli muhitlar (dev/prod — 10) uchun zarur.
Foydalanilgan rasmiy/ishonchli manbalar
- Microsoft Azure Architecture — Web API Design Best Practices
- Stack Overflow Blog — Best practices for REST API design
- Postman Blog — REST API Best Practices; MDN — HTTP (0.4)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!