RESTful best practices — naming, status codes, idempotency

~20 daq · .NET Backend · API Sifati va Dizayn

Muammodan boshlaylik

Bir loyihadagi endpoint lar:

GET  /api/getAllProducts
POST /api/product/create
GET  /api/Mahsulot/ol?id=5
POST /api/deleteProduct/5
GET  /api/orders_list

Har biri boshqacha: fe'l URL da, birlik va ko'plik aralash, katta-kichik harf, o'chirish POST bilan. Frontend dasturchi har bir endpoint uchun hujjatni qayta o'qiydi; yangi xodim qanday nomlashni bilmaydi.


Hayotiy o'xshatma

Shahar manzillari. Yaxshi rejalashtirilgan shaharda manzil tartibli: "Toshkent, Chilonzor tumani, 9-kvartal, 15-uy". Uyni topish uchun xarita shart emas — tuzilmadan tushunasiz. Tartibsiz shaharda har bir uyga yo'lni so'rab-so'rab topasiz. REST qoidalari — API uchun manzil tizimi.


1. URL — resurs (ot), metod — amal (fe'l)

❌ ✅
GET /getProducts GET /mahsulotlar
POST /createProduct POST /mahsulotlar
POST /deleteProduct/5 DELETE /mahsulotlar/5
GET /product/5 GET /mahsulotlar/5
GET    /api/mahsulotlar          ro'yxat
GET    /api/mahsulotlar/5        bittasi
POST   /api/mahsulotlar          yaratish
PUT    /api/mahsulotlar/5        to'liq yangilash
PATCH  /api/mahsulotlar/5        qisman yangilash
DELETE /api/mahsulotlar/5        o'chirish

Qoidalar:

  • Ko'plik: /mahsulotlar, /buyurtmalar
  • Kichik harf, so'zlar defis bilan: /yetkazib-berish-manzillari
  • Oxirida / siz

2. Ichma-ich resurslar — bir daraja

GET  /api/buyurtmalar/42/qatorlar          42-buyurtmaning qatorlari
POST /api/buyurtmalar/42/qatorlar          qator qo'shish
GET  /api/mijozlar/7/buyurtmalar           mijozning buyurtmalari

Chuqur ichma-ichlikdan qoching: /mijozlar/7/buyurtmalar/42/qatorlar/3/mahsulot — o'rniga /qatorlar/3 yoki /mahsulotlar/9.

CRUD ga sig'maydigan amallar

POST /api/buyurtmalar/42/bekor-qilish
POST /api/buyurtmalar/42/tolov
POST /api/foydalanuvchilar/7/parol-tiklash

Holat o'zgartiradigan biznes amal — resurs ostidagi fe'l bilan POST. Bu maqbul va keng tarqalgan.


3. Status kodlar — to'g'ri ishlating

Holat Kod
O'qish muvaffaqiyatli 200 OK
Yaratildi 201 Created + Location sarlavhasi
Muvaffaqiyatli, body yo'q (DELETE, PUT) 204 No Content
Noto'g'ri so'rov / validatsiya 400 Bad Request
Token yo'q 401 Unauthorized
Huquq yo'q 403 Forbidden
Topilmadi 404 Not Found
Ziddiyat (dublikat, versiya) 409 Conflict
Biznes qoida buzildi 422 Unprocessable Entity
Limit oshdi 429 Too Many Requests
Server xatosi 500 Internal Server Error
[HttpPost]
public async Task<ActionResult<MahsulotDto>> Yarat(MahsulotYaratDto dto, CancellationToken ct)
{
    var m = await service.YaratAsync(dto, ct);
    return CreatedAtAction(nameof(Ol), new { id = m.Id }, m);    // 201 + Location
}

[!WARNING] Xatoni 200 OK + { "success": false, "error": "..." } bilan qaytarmang. HTTP kutubxonalar, monitoring, cache va proxy lar status kodiga qaraydi — 200 ko'rib, "hammasi joyida" deb hisoblaydi.


4. Ro'yxatlar — filtrlash, saralash, sahifalash

GET /api/mahsulotlar?kategoriya=telefon&minNarx=1000000&saralash=-narx&sahifa=2&hajm=20
public record MahsulotSorov(
    string? Kategoriya, decimal? MinNarx, string? Saralash,
    int Sahifa = 1, int Hajm = 20);

[HttpGet]
public async Task<SahifaJavob<MahsulotDto>> Royxat([FromQuery] MahsulotSorov s, CancellationToken ct)
{
    var hajm = Math.Clamp(s.Hajm, 1, 100);              // maksimal chegarani majburlash
    // ...
}
{
  "elementlar": [ { "id": 31, "nomi": "Telefon X" } ],
  "sahifa": 2,
  "hajm": 20,
  "jami": 347
}

[!TIP] Hech qachon cheklanmagan ro'yxat qaytarmang — GET /api/buyurtmalar 2 million qator qaytarib, serverni yiqitishi mumkin. Sukut bo'yicha sahifalash va maksimal hajm (masalan, 100). Juda katta, tez o'zgaradigan to'plamlar uchun — cursor asosidagi sahifalash (?keyingi=eyJpZCI6MTAwfQ).


5. Izchil javob formati

  • JSON nomlari — camelCase (ASP.NET Core sukut bo'yicha)
  • Sanalar — ISO 8601, UTC: "2026-11-08T14:30:00Z"
  • Pul — decimal; valyuta aniq bo'lsin
  • Xatolar — ProblemDetails (65-dars)
  • Enum lar — satr sifatida ("Yetkazilmoqda", raqam emas):
builder.Services.AddControllers()
    .AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

6. Idempotentlik

Metod Idempotent?
GET, PUT, DELETE ✅ — bir necha marta = bir marta
POST ❌ — har safar yangi resurs

Tarmoq uzilib mijoz POST ni qayta yuborsa — ikkita buyurtma. Muhim POST larda (to'lov) — Idempotency-Key sarlavhasi: server kalitni eslab qoladi va takroriy so'rovga avvalgi natijani qaytaradi.


7. Versiyalash va hujjat

  • Buzuvchi o'zgarishlar — yangi versiya: /api/v2/... (73-dars)
  • Hujjat — OpenAPI/Swagger (72-dars)

Tez-tez uchraydigan xatolar

GET bilan holat o'zgartirish (GET /api/buyurtmalar/5/bekor) — brauzer oldindan yuklashi, crawler yoki cache uni tasodifan chaqiradi.

Entity ni to'g'ridan-to'g'ri qaytarish — ichki maydonlar oshkor; DTO (45-dars).

Javoblarda turli nomlash — product_name, ProductName, productName aralash.


Xulosa

URL — resurs (ko'plikdagi ot, kichik harf, defis), amal — HTTP metodi. Ichma-ichlik — bir daraja; CRUD ga sig'maydigan amallar — POST /resurs/{id}/amal. Status kodlar to'g'ri: 201 + Location, 204, 400/401/403/404/409/422/429; xato — hech qachon 200 bilan emas.

Ro'yxatlar — filtr, saralash va majburiy sahifalash. Izchil format: camelCase, ISO 8601 UTC, ProblemDetails, enum — satr. POST idempotent emas — muhim amallarda Idempotency-Key. Versiyalash va OpenAPI hujjat.


Keyingi dars

72-dars: Swagger / OpenAPI — avtomatik hujjat, Scalar, XML comments