IlmHamroh
JavaScript Full-stack/25-qism. HTTP, Express va REST API18/51-dars16 daqiqa
Mundarija (20)

REST API prinsiplari: resurslar, URI nomlash va 6 cheklov

Qisqacha: REST — API'ni resurslar (otlar: /vazifalar, /vazifalar/7) va HTTP metodlari (fe'llar: GET, POST, PATCH, DELETE) atrofida qurish uslubi. URI'da fe'l bo'lmaydi (/vazifaQosh emas — POST /vazifalar), to'plam ko'plikda, so'zlar kebab-case bilan yoziladi. Roy Fielding 2000 yilda REST'ni 6 cheklov bilan ta'riflagan: mijoz-server, holatsizlik, keshlanish, yagona interfeys, qatlamli tizim va ixtiyoriy "talab bo'yicha kod". Ichma-ich resurslar bir darajadan chuqur bo'lmagani ma'qul.

Bu darsda

  • REST'ning 6 cheklovini oddiy so'zlar bilan tushuntira olasiz.
  • Resurs nima ekanini va unga URI qanday berilishini bilasiz.
  • URI nomlash qoidalarini (ko'plik, kebab-case, fe'lsiz) qo'llaysiz.
  • Ichma-ich resurs qachon kerak va qachon filtr yaxshiroq — ajrata olasiz.
  • vazifalar-api ga hosila resurs /teglar ni qo'shasiz.

Oldin bilishingiz kerak: HTTP metodlari va status kodlari, express.Router va qatlamli tuzilma, Express + TypeScript.

1. Nega bu kerak?

Tasavvur qiling, uch dasturchi bir API yozdi. Biri /getTasks qildi, ikkinchisi /task/list, uchinchisi /vazifalarni_olish. Yangi vazifa qo'shish uchun biri /addTask, boshqasi POST /task/create. Frontend dasturchi har endpoint uchun hujjat o'qishi kerak — qoidaga tayanib bo'lmaydi.

REST shu tartibsizlikka yechim. U API'ni bitta mantiq bilan quradi: har "narsa" — resurs, uning manzili bor, ustidagi amallar — HTTP metodlari. Shunda /vazifalar ni ko'rgan dasturchi /teglar qanday ishlashini taxmin qila oladi.

O'xshatish: kutubxona. Har kitobning javon raqami bor (URI). Kitob bilan nima qilish — olish, qaytarish, yangisini qo'shish — kutubxonaning umumiy qoidalari (metodlar). Siz "Navoiy kitobini olish xonasi"ni qidirmaysiz — kitob raqamini aytib, "olaman" deysiz.

Siz 25-qism davomida REST'ni allaqachon ishlatib keldingiz: GET /vazifalar, POST /vazifalar, DELETE /vazifalar/7. Bu darsda uning nazariyasi va nomlash qoidalari keladi. Keyingi to'rt darsda — metodlar, status kodlar, filtrlar va sahifalash.

2. REST nima

2.1 Kelib chiqishi

REST (Representational State Transfer — "holatni tasvir orqali uzatish") — Roy Fielding'ning 2000 yildagi doktorlik dissertatsiyasidagi arxitektura uslubi. Fielding HTTP standartining mualliflaridan biri. U Web nega shunchalik yaxshi kengayganini tahlil qilib, uning qoidalarini 6 cheklovga jamladi.

REST — protokol ham, standart ham emas. Bu uslub: "shunday qurilsa, tizim yaxshi kengayadi" degan tavsiyalar to'plami. Shuning uchun "bu API REST'mi?" degan bahslar ko'p. Amalda "REST API" deganda ko'pincha "resurslar + HTTP metodlari + JSON" tushuniladi.

2.2 Oltita cheklov

Cheklov Ma'nosi vazifalar-api da
Mijoz-server UI va ma'lumot alohida React frontend ↔ Express API
Holatsizlik (stateless) Har so'rov o'zi yetarli Server "oldingi so'rov"ni eslamaydi
Keshlanish Javob keshlanadimi — aniq aytiladi ETag, keyinroq Cache-Control
Yagona interfeys Resurs + metod + tasvir /vazifalar/:id + GET/PATCH/DELETE (PUT — keyingi darsda)
Qatlamli tizim Mijoz o'rtadagi proxy'ni bilmaydi nginx oldida bo'ladi
Talab bo'yicha kod Server mijozga kod yuborishi mumkin ixtiyoriy, ishlatilmaydi

Ikkitasini batafsil ko'raylik — ular eng ko'p xato qilinadigan joylar.

Holatsizlik (statelessness). Har so'rov kerakli hamma narsani o'zi olib keladi. Server "bu foydalanuvchi oldin 2-sahifani so'ragan edi" deb eslab qolmaydi. Shuning uchun keyingi sahifa so'rovida offset yoki kursor yuboriladi (Pagination darsi). Bu nimaga kerak? Server nusxalari ko'payganda istalgan so'rov istalgan nusxaga tushishi mumkin. Agar holat bitta nusxaning xotirasida bo'lsa, boshqa nusxa uni bilmaydi.

Ma'lumotlar (vazifalar) albatta serverda saqlanadi — holatsizlik ular haqida emas. Gap so'rovlar orasidagi suhbat holati haqida.

Yagona interfeys (uniform interface). Har resurs bir xil qoidalar bilan boshqariladi: manzil (URI), standart metodlar va tasvir (JSON). Mijoz resursning o'zini emas, uning tasvirini (representation) oladi. Serverda vazifa — xotiradagi obyekt yoki jadval qatori. Mijozga esa uning JSON tasviri boradi. Nomdagi "Representational" shundan.

Tekshirib ko'ring: Server foydalanuvchining "joriy filtri"ni xotirada saqlaydi: avval POST /filtr (bajarildi=true), keyin GET /vazifalar shu filtr bilan qaytadi. Qaysi cheklov buzilgan va bu amalda qanday muammo beradi?

Javob

Holatsizlik buzilgan: GET /vazifalar ning natijasi oldingi so'rovga bog'liq. Muammolar: ikkinchi server nusxasi filtrni bilmaydi; havolani boshqa odamga yuborsangiz, u boshqa natija ko'radi; keshlab bo'lmaydi. To'g'ri yo'l — filtr har so'rovda: GET /vazifalar?bajarildi=true (Filtrlash darsi).

3. Resurs va URI

3.1 Resurs nima

Resurs (resource) — nomga ega bo'lishi mumkin bo'lgan har qanday narsa: bitta vazifa, vazifalar ro'yxati, teglar statistikasi, foydalanuvchi profili. Har resursning URI'si (manzil) bor.

Ikki asosiy tur:

  • To'plam (collection) — /vazifalar: ko'p narsalar ro'yxati. GET — ro'yxat, POST — yangisini qo'shish.
  • Element (item) — /vazifalar/7: bitta narsa. GET, PUT, PATCH, DELETE.

Uchinchi tur ham bor — hosila resurs: bazada alohida saqlanmaydi, boshqa ma'lumotdan hisoblanadi. Masalan, "har tegda nechta vazifa" — teglar alohida saqlanmaydi, vazifalar matnidan ajratiladi. Lekin mijoz uchun bu ham resurs: /teglar.

3.2 Nomlash qoidalari

Qoida
Ot, fe'l emas POST /vazifalar POST /vazifaQosh
To'plam ko'plikda /vazifalar/7 /vazifa/7
Kichik harf, kebab-case /tolov-usullari /tolovUsullari, /Tolov_Usullari
Oxirida / yo'q /vazifalar /vazifalar/
Fayl kengaytmasi yo'q /vazifalar/7 /vazifalar/7.json
ID — o'zgarmas /vazifalar/7 /vazifalar/non-olish (matn o'zgaradi)

Nega kebab-case? URI'da katta va kichik harf farq qiladi (domendan tashqari). /Vazifalar va /vazifalar — ikki xil manzil. Kichik harf bu chalkashlikni yo'qotadi. Pastki chiziq (_) esa havolaning tagiga chizilgan chiziq ostida ko'rinmay qoladi.

Nega ko'plik? /vazifalar — to'plam, /vazifalar/7 — "to'plamdagi 7-si". Mantiq bir xil ketadi. /vazifa va /vazifalar ni aralashtirsangiz, har safar "qaysi edi?" deb o'ylaysiz.

Fe'l kerak bo'lib qolsa-chi? Masalan, "vazifani bajarilgan deb belgilash". REST usuli — holatni o'zgartirish: PATCH /vazifalar/7 tanasi {"bajarildi": true}. Ba'zan haqiqatan ham resursga sig'maydigan amal bo'ladi ("hisobotni qayta hisoblash"). Bunday holatlar API konvensiyalari darsida ko'riladi.

Quyidagi toza funksiya URI'ni shu qoidalar bo'yicha tekshiradi. «Ishga tushir» bilan sinang va o'z misollaringizni qo'shing:

js
const FELLAR = [
  "get", "ol", "qosh", "add", "create", "ochir", "delete",
];

function uriTekshir(uri) {
  const xatolar = [];
  if (uri !== "/" && uri.endsWith("/")) xatolar.push("oxirida /");
  if (/[A-Z]/.test(uri)) xatolar.push("katta harf");
  if (uri.includes("_")) xatolar.push("pastki chiziq");
  if (/\.\w+$/.test(uri)) xatolar.push("kengaytma");
  const segmentlar = uri.split("/").filter(Boolean);
  for (const s of segmentlar) {
    const kichik = s.toLowerCase();
    if (FELLAR.some((f) => kichik.startsWith(f))) {
      xatolar.push(`fe'l: ${s}`);
    }
  }
  return xatolar.length === 0 ? "ok" : xatolar.join(", ");
}

for (const uri of ["/vazifalar/7", "/getTasks", "/tolov_usullari/",
  "/vazifalar/7.json", "/qoshVazifa"]) {
  console.log(uri, "→", uriTekshir(uri));
}

Konsolda:

text
/vazifalar/7 → ok
/getTasks → katta harf, fe'l: getTasks
/tolov_usullari/ → oxirida /, pastki chiziq
/vazifalar/7.json → kengaytma
/qoshVazifa → katta harf, fe'l: qoshVazifa

Bu — oddiy evristika, hamma holatni ushlamaydi ("olma" so'zi "ol" bilan boshlanadi). Lekin kod sharhida tez tekshiruv uchun yetadi.

Maslahat: Express yo'llarni sukut bo'yicha katta-kichik harfga sezgir emas deb biladi (/Vazifalar ham ishlaydi), oxiridagi / ni ham kechiradi. Bu qulaylik, lekin API hujjatida faqat bitta to'g'ri shakl bo'lsin.

4. Ichma-ich resurslar

Ba'zi resurslar boshqasiga tegishli: buyurtmaning taomlari, foydalanuvchining manzillari. URI'da bu ichma-ichlik (nesting) bilan ifodalanadi:

text
GET /buyurtmalar/17/taomlar      — 17-buyurtmaning taomlari
POST /buyurtmalar/17/taomlar     — 17-buyurtmaga taom qo'shish

Qachon ichma-ich qilish kerak? Bola resurs ota resurssiz mavjud bo'lmasa. Buyurtmadagi taom qatori boshqa buyurtmada yashamaydi. Shuning uchun /buyurtmalar/17/taomlar mantiqli.

Chegarasi — bir daraja. Chuqurroq URI'lar mo'rt bo'ladi:

text
❌ /oshxonalar/3/menyular/2/taomlar/45/sharhlar/9
✅ /sharhlar/9
✅ /taomlar/45/sharhlar

Uzun URI'ning muammosi: sharhni o'zgartirish uchun mijoz to'rtta ID'ni bilishi kerak. Taom boshqa menyuga ko'chsa, sharhning manzili ham o'zgaradi. Element o'zining global ID'si bilan yuqori darajada tursa, manzil barqaror bo'ladi.

flowchart TD
  R["/"] --> V["/vazifalar<br/>to'plam"]
  V --> V7["/vazifalar/:id<br/>element"]
  R --> T["/teglar<br/>hosila resurs"]
  V -. "teg — filtr" .-> F["/vazifalar?teg=uy"]

Diagrammada vazifalar-api ning resurs xaritasiga qarang. Uzuq chiziq — muhim qaror: teg bo'yicha vazifalar uchun ichma-ich /teglar/uy/vazifalar emas, filtr ?teg=uy tanlangan.

Nega? Tegning o'zi resurs emas — u vazifa matnining bir qismi (#uy). Vazifa bir nechta tegga ega bo'lishi mumkin: Sut #uy #bozor. Agar /teglar/uy/vazifalar bo'lsa, shu vazifa /teglar/bozor/vazifalar da ham chiqadi — bitta elementning ikki "uyi" bo'ladi. Filtr bilan esa to'plam bitta, faqat ko'rinishi o'zgaradi: ?teg=uy&teg=bozor — ikkala tegli vazifalar. Qoida: ichma-ich — egalik uchun, filtr — tanlash uchun.

Tekshirib ko'ring: «Bahor» oshxonasi API'si uchun qaysi biri yaxshiroq: GET /taomlar/osh/narx yoki GET /taomlar/12? Narxni qanday o'zgartirasiz?

Javob

GET /taomlar/12. Birinchisida ikki muammo: osh — nom, ID emas (nom o'zgarsa manzil buziladi); narx — taomning maydoni, alohida resurs emas. Narx PATCH /taomlar/12 bilan o'zgaradi, tanasi {"narx": 37000}. Faqat narx kerak bo'lsa — maydon tanlash: GET /taomlar/12?fields=narx (Filtrlash darsi).

5. REST va boshqa uslublar

REST yagona yo'l emas. Uni boshqalar bilan qisqacha taqqoslaymiz (har biri keyingi qismlarda alohida):

Uslub G'oya Qachon
REST Resurs + HTTP metodlari Ko'p ochiq va ichki API'lar
RPC (JSON-RPC, gRPC) Funksiya chaqirish: vazifaQosh(...) Xizmatlar orasida, tezlik
GraphQL Mijoz o'zi so'rov yozadi Murakkab, ko'p ekranli frontend
Server Actions Funksiya, freymvork tarmoqni yashiradi Next.js ichida (Server Actions)

Siz Server Actions'ni bilasiz: u RPC uslubiga yaqin — frontend serverdagi funksiyani "chaqiradi". REST'ning ustunligi — HTTP'ning o'zi bilan ishlashi: kesh, proxy, curl bilan tekshirish, istalgan til va qurilma. vazifalar frontend'i Vite'dagi oddiy React ilova, Next.js emas — unga REST mos keladi.

6. API qadami: /teglar resursi (holat 22, 1-qism)

Holat 22 besh darsga bo'lingan: resurslar (bugun), metodlar, status kodlar, filtrlar va sahifalash. Hali commit qilmang — commit beshinchi darsda.

Kanon resurs xaritasi:

Resurs URI Tur
Vazifalar /vazifalar to'plam
Bitta vazifa /vazifalar/:id element
Teglar statistikasi /teglar hosila resurs

Bugungi qadam — /teglar. Javob shakli: { "teglar": [{ "teg": "uy", "soni": 2 }, …] }, ko'pidan kamiga. Uch qatlamdan o'tadi (qatlamli tuzilma).

  1. Ombor interfeysi (src/vazifalar/ombor.ts) — yangi tip va metod:
ts
export type TegSoni = { teg: string; soni: number };

export interface VazifaOmbori {
  // … oldingi metodlar
  /** teglar va nechta vazifada — ko'pidan kamiga */
  teglar(): Promise<TegSoni[]>;
}
  1. Xotiradagi amalga oshirish (xotira-ombor.ts, kanon mantig'i). Uni toza JS'da qayta yozamiz — «Ishga tushir» bilan sinang:
js
function teglarSoni(vazifalar) {
  const sanoq = new Map();
  for (const v of vazifalar) {
    for (const t of v.teglar) sanoq.set(t, (sanoq.get(t) ?? 0) + 1);
  }
  return [...sanoq]
    .map(([teg, soni]) => ({ teg, soni }))
    // ko'pidan kamiga; teng bo'lsa — alifbo bo'yicha
    .sort((a, b) => b.soni - a.soni || (a.teg < b.teg ? -1 : 1));
}

const vazifalar = [
  { matn: "Non olish #uy", teglar: ["uy"] },
  { matn: "Hisobot #ish", teglar: ["ish"] },
  { matn: "Sut #uy #bozor", teglar: ["uy", "bozor"] },
  { matn: "Yig'ilish #ish", teglar: ["ish"] },
  { matn: "Kitob o'qish #o'quv", teglar: ["o'quv"] },
];
console.log(JSON.stringify({ teglar: teglarSoni(vazifalar) }));

Konsolda:

text
{"teglar":[{"teg":"ish","soni":2},{"teg":"uy","soni":2},{"teg":"bozor","soni":1},{"teg":"o'quv","soni":1}]}

Ikkinchi saralash kaliti (a.teg < b.teg) muhim: usiz teng sonli teglar tartibi kiritish tartibiga bog'liq bo'lardi. Testlar va kesh barqaror tartib talab qiladi. Bu natija kanon curl $A/teglar chiqishi bilan aynan bir xil (o'sha besh vazifa).

XotiraOmbori dagi TypeScript metodi — xuddi shu mantiq (kanon, qatorlar bo'lingan; klass oxiriga qo'shiladi, importga TegSoni qo'shing):

ts
teglar(): Promise<TegSoni[]> {
  const sanoq = new Map<string, number>();
  for (const v of this.#vazifalar.values()) {
    for (const t of v.teglar) sanoq.set(t, (sanoq.get(t) ?? 0) + 1);
  }
  return Promise.resolve(
    [...sanoq]
      .map(([teg, soni]) => ({ teg, soni }))
      .sort((a, b) => b.soni - a.soni || (a.teg < b.teg ? -1 : 1)),
  );
}
  1. Xizmat va router (xizmat.ts, marshrut.ts, ilova.ts):
ts
// xizmat.ts
teglar: (): Promise<TegSoni[]> => ombor.teglar(),

// marshrut.ts
export function teglarRouteri(xizmat: VazifaXizmati): Router {
  const r = Router();
  r.route("/")
    .get(async (_req, res) => {
      res.json({ teglar: await xizmat.teglar() });
    })
    .all(metodYoq("GET, HEAD"));
  return r;
}

// ilova.ts
const xizmat = vazifaXizmati(ombor);
app.use("/vazifalar", vazifalarRouteri(xizmat));
app.use("/teglar", teglarRouteri(xizmat));

Javob nega massiv emas, obyekt ({ teglar: [...] })? Kelajakda maydon qo'shish oson bo'ladi (masalan jami), mijoz kodi buzilmaydi. Bir xil sabab bilan GET /vazifalar ham holat 22 da { vazifalar, sahifa } qaytaradi (sahifalash darsida). vazifalar frontend'ini API'ga ulash — Coverage darsining «Frontend'ni ulash» bo'limida.

/teglar — hosila resurs, shuning uchun faqat GET va HEAD. Teg qo'shish — vazifa matniga #teg yozish orqali. POST /teglar ga 405 va Allow: GET, HEAD qaytadi.

Ombor teglar() ni bilganining foydasi: Postgres qismida u SQL'da hisoblanadi (GROUP BY), xizmat va router o'zgarmaydi.

7. Ko'p uchraydigan xatolar

Xato Nega yomon To'g'risi
/getVazifalar, /vazifaQosh Fe'l metodni takrorlaydi GET /vazifalar, POST /vazifalar
/vazifa va /vazifalar aralash Taxmin qilib bo'lmaydi Doim ko'plik
/foydalanuvchilar/5/vazifalar/7/teglar/2 Mo'rt, ko'p ID Bir daraja yoki global ID
POST /vazifalar/7/bajarildi Holat o'zgarishi alohida "amal" PATCH /vazifalar/7
Server "joriy sahifa"ni eslaydi Holatsizlik buziladi Har so'rovda parametr
Nom bilan URI (/taomlar/osh) Nom o'zgaradi ID bilan

8. Mashqlar

Yechimlar kurs/mashqlar/25/18-rest-resurslar/ da.

1-mashq (oson): to'g'ri URI'ni tanlang

  • Barcha taomlar ro'yxati:
  • 12-taomni o'chirish:
  • 17-buyurtmaning taomlari:
  • REST cheklovi: "server oldingi so'rovni eslamaydi" —
Yechim
  • GET /taomlar — to'plam, ko'plik, fe'lsiz.
  • DELETE /taomlar/12 — amal metodda, URI'da emas.
  • GET /buyurtmalar/17/taomlar — taom qatori buyurtmasiz yashamaydi, bir daraja.
  • holatsizlik (stateless) — har so'rov o'zi yetarli.

2-mashq (o'rta): «Bahor» resurs xaritasi

«Bahor» oshxonasi uchun API loyihalang: menyu (taomlar), buyurtmalar, buyurtma qatorlari, taom sharhlari va "eng ko'p buyurtma qilingan taomlar" statistikasi. Har resurs uchun URI, turi (to'plam, element, hosila) va metodlar. Natijani { uri, tur, metodlar } massivi qilib yozing va uriTekshir (yuqorida) bilan hamma URI'ni tekshiring.

Yechim
js
const FELLAR = [
  "get", "ol", "qosh", "add", "create", "ochir", "delete",
];
function uriTekshir(uri) {
  const segmentlar = uri.split("/").filter(Boolean);
  const yomon = /[A-Z_]/.test(uri) || uri.endsWith("/") ||
    segmentlar.some((s) => FELLAR.some((f) => s.startsWith(f)));
  return yomon ? "XATO" : "ok";
}

const xarita = [
  { uri: "/taomlar", tur: "to'plam", metodlar: "GET, POST" },
  { uri: "/taomlar/:id", tur: "element",
    metodlar: "GET, PUT, PATCH, DELETE" },
  { uri: "/taomlar/:id/sharhlar", tur: "to'plam",
    metodlar: "GET, POST" },
  { uri: "/sharhlar/:id", tur: "element",
    metodlar: "GET, PATCH, DELETE" },
  { uri: "/buyurtmalar", tur: "to'plam", metodlar: "GET, POST" },
  { uri: "/buyurtmalar/:id", tur: "element", metodlar: "GET, PATCH" },
  { uri: "/buyurtmalar/:id/qatorlar", tur: "to'plam",
    metodlar: "GET, POST" },
  { uri: "/mashhur-taomlar", tur: "hosila", metodlar: "GET" },
];
for (const r of xarita) {
  const holat = uriTekshir(r.uri);
  console.log(`${holat} ${r.uri} (${r.tur}): ${r.metodlar}`);
}

Konsolda:

text
ok /taomlar (to'plam): GET, POST
ok /taomlar/:id (element): GET, PUT, PATCH, DELETE
ok /taomlar/:id/sharhlar (to'plam): GET, POST
ok /sharhlar/:id (element): GET, PATCH, DELETE
ok /buyurtmalar (to'plam): GET, POST
ok /buyurtmalar/:id (element): GET, PATCH
ok /buyurtmalar/:id/qatorlar (to'plam): GET, POST
ok /mashhur-taomlar (hosila): GET

E'tibor bering: sharh yaratish ichma-ich (POST /taomlar/:id/sharhlar — qaysi taomga ekani URI'dan), lekin bitta sharh bilan ishlash yuqori darajada (/sharhlar/:id). Buyurtma DELETE siz — buyurtma o'chirilmaydi, PATCH bilan holati "bekor qilindi" bo'ladi (pul bilan bog'liq ma'lumot izsiz yo'qolmasin).

3-mashq (qiyin): teglar statistikasi kengaytmasi

teglarSoni(vazifalar, { bajarildi }) ni yozing: ikkinchi parametr berilsa, faqat shu holatdagi vazifalar sanalsin. Teglar kichik harfga keltirilsin (#Uy va #uy — bitta teg). Natija — ko'pidan kamiga, teng bo'lsa alifbo bo'yicha. Yordam: Map, filter — Map darsi.

Yechim
js
function teglarSoni(vazifalar, { bajarildi } = {}) {
  const sanoq = new Map();
  const tanlangan = bajarildi === undefined
    ? vazifalar
    : vazifalar.filter((v) => v.bajarildi === bajarildi);
  for (const v of tanlangan) {
    for (const t of new Set(v.teglar.map((x) => x.toLowerCase()))) {
      sanoq.set(t, (sanoq.get(t) ?? 0) + 1);
    }
  }
  return [...sanoq]
    .map(([teg, soni]) => ({ teg, soni }))
    .sort((a, b) => b.soni - a.soni || (a.teg < b.teg ? -1 : 1));
}

const vazifalar = [
  { teglar: ["uy"], bajarildi: false },
  { teglar: ["Uy", "bozor"], bajarildi: true },
  { teglar: ["ish", "ISH"], bajarildi: true },
  { teglar: ["ish"], bajarildi: false },
];
console.log(JSON.stringify(teglarSoni(vazifalar)));
const bajarilgan = teglarSoni(vazifalar, { bajarildi: true });
console.log(JSON.stringify(bajarilgan));

Konsolda:

text
[{"teg":"ish","soni":2},{"teg":"uy","soni":2},{"teg":"bozor","soni":1}]
[{"teg":"bozor","soni":1},{"teg":"ish","soni":1},{"teg":"uy","soni":1}]

new Set(...) — bitta vazifada #ish #ISH ikki marta sanalmasin. HTTP'da bu GET /teglar?bajarildi=true bo'lardi — filtr, yangi resurs emas.

4-mashq: API qadami

TegSoni tipi va teglar() metodini ombor interfeysiga, XotiraOmbori ga, xizmatga qo'shing; teglarRouteri ni yozib /teglar ga ulang. Test: olti vazifa yarating va GET /teglar ning birinchi uchta elementini tekshiring. POST /teglar → 405. npm test — yashil. Commit qilmang.

Yechim

Kanon testi (test/rest.test.ts) olti vazifa bilan (Non olish #uy, Hisobot #ish, Sut #uy #bozor, Kitob o'qish #o'quv, Yig'ilish #ish, Olma #bozor):

ts
test("/teglar — ko'pidan kamiga", async () => {
  const r = await fetch(`${asos}/teglar`);
  const { teglar } = (await r.json()) as {
    teglar: { teg: string; soni: number }[];
  };
  assert.deepEqual(teglar.slice(0, 3), [
    { teg: "bozor", soni: 2 },
    { teg: "ish", soni: 2 },
    { teg: "uy", soni: 2 },
  ]);
});

Uchala teg 2 tadan — tartibni alifbo hal qiladi. 405 ni tekshirish uchun shu testga qo'shing:

ts
const p = await fetch(`${asos}/teglar`, { method: "POST" });
assert.equal(p.status, 405);
assert.equal(p.headers.get("allow"), "GET, HEAD");

Kanon rest.test.ts ning before() qismi olti vazifani yaratadi; qolgan testlari (PUT, filtr, sahifalash) keyingi darslarda qo'shiladi. Biz bugungi kesimni holat 17 nusxasida tekshirdik (Node 24.21.0): tip 0, lint 0, testlar 11/11.

9. Real ishda

  • Ochiq API'lar. GitHub va Stripe API'lari REST qoidalariga yaqin: GET /repos/{owner}/{repo}/issues. Telegram Bot API esa RPC uslubida: /sendMessage, /getUpdates — URI'da fe'l. Ikkalasini solishtirib o'qish — yaxshi mashq.
  • Intervyu: "REST nima?", "Holatsizlik nimani anglatadi?", "PUT va PATCH farqi?" (keyingi dars), "URI'ni qanday nomlaysiz?".
  • Kod sharhi: yangi endpoint nomi — eng ko'p bahs bo'ladigan joy. Jamoaviy qoidalar hujjati (style guide) shuning uchun yoziladi (API konvensiyalari).

Xulosa

  • REST — resurslar (otlar) + HTTP metodlari (fe'llar) + tasvir (JSON); Fielding, 2000, 6 cheklov.
  • Holatsizlik: har so'rov o'zi yetarli; ma'lumot serverda, "suhbat holati" — yo'q.
  • URI: ko'plik, kichik harf, kebab-case, fe'lsiz, oxirida / siz, ID bilan.
  • Ichma-ich — egalik uchun va bir daraja; tanlash uchun — filtr (?teg=uy).
  • vazifalar-api resurslari: /vazifalar, /vazifalar/:id, hosila /teglar.

Keyingi dars: HTTP metodlari semantikasi — xavfsiz va idempotent metodlar, PUT va PATCH farqi, JSON Merge Patch.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
REST API prinsiplari: resurslar, URI nomlash va 6 cheklov — IlmHamroh