11-bo‘lim

API loyihalash

REST prinsiplari, resurs nomlari, HTTP kodlari, xatolarni qaytarish, versiyalash va OpenAPI hujjati.

🕑 18 daqiqa o‘qish 📄 1 195 so‘z 👁 6 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. REST asoslari
  2. Resurs nomlari
  3. Amallar uchun
  4. HTTP holat kodlari
  5. So'rov va javob formati
  6. Xatolarni qaytarish
  7. Sahifalash
  8. Filtrlash, saralash, tanlash
  9. Autentifikatsiya
  10. Chegaralash
  11. Versiyalash
  12. Idempotentlik
  13. OpenAPI hujjati
  14. REST ga muqobil
  15. API loyihalash tekshiruv ro'yxati
  16. Xulosa

API - tizimingizning tashqi dunyo bilan shartnomasi. Uni o'zgartirish qiyin, shuning uchun boshidanoq to'g'ri loyihalash muhim.

REST asoslari #

REST - resurslarga asoslangan yondashuv: har bir narsa resurs, unga HTTP metodlari qo'llanadi.

HTTP metodlari va ularning ma'nosi GET /api/mahsulotlar Ro'yxatni olish xavfsiz, idempotent POST /api/mahsulotlar Yangi yaratish idempotent emas PUT /api/mahsulotlar/42 To'liq almashtirish idempotent PATCH /api/mahsulotlar/42 Qisman yangilash odatda idempotent DELETE /api/mahsulotlar/42 O'chirish idempotent Idempotent - bir necha marta chaqirilsa ham natija bir xil
Metod ma'nosini o'zgartirmang - bu umumiy kelishuv
GET hech nima o'zgartirmasin
Natija
GET /api/mahsulotlar/42/ochirish     ← XATO

Nima uchun xavfli:

  • Brauzer va proksi GET so'rovlarini keshlaydi
  • Qidiruv robotlari havolalarni avtomatik ochadi
  • Foydalanuvchi sahifani yangilasa - amal takrorlanadi

Ma'lum bir loyihada qidiruv roboti barcha "o'chirish" havolalarini bosib chiqqan va butun katalogni o'chirgan.

Resurs nomlari #

Nomlash qoidalari
QoidaYomonYaxshi
Ot ishlating, fe'l emas/getMahsulot/mahsulotlar
Ko'plik shakli/mahsulot/42/mahsulotlar/42
Kichik harflar/Mahsulotlar/mahsulotlar
Chiziqcha, pastki chiziq emas/buyurtma_elementlari/buyurtma-elementlari
Ierarxiya/buyurtmaElementlari?id=5/buyurtmalar/5/elementlar
Oxirida / yo'q/mahsulotlar//mahsulotlar
Natija
GET    /api/v1/mahsulotlar                  ro'yxat
POST   /api/v1/mahsulotlar                  yaratish
GET    /api/v1/mahsulotlar/42               bitta
PUT    /api/v1/mahsulotlar/42               to'liq yangilash
PATCH  /api/v1/mahsulotlar/42               qisman yangilash
DELETE /api/v1/mahsulotlar/42               o'chirish

GET    /api/v1/mahsulotlar/42/sharhlar      ichki resurs
POST   /api/v1/mahsulotlar/42/sharhlar      sharh qo'shish

GET    /api/v1/buyurtmalar/17/elementlar

Amallar uchun #

Ba'zi amallar CRUD ga to'g'ri kelmaydi:

Natija
POST /api/v1/buyurtmalar/17/bekor-qilish
POST /api/v1/mahsulotlar/42/nashr-qilish
POST /api/v1/foydalanuvchilar/8/parolni-tiklash
POST /api/v1/sessiyalar                     (kirish)
DELETE /api/v1/sessiyalar/joriy             (chiqish)
Amalni resurs sifatida ko'ring

POST /api/v1/buyurtmalar/17/bekor-qilish - "bekor qilish so'rovini yaratish" degan ma'noda.

Bu sof REST emas, lekin amaliy va tushunarli.

HTTP holat kodlari #

Eng ko'p ishlatiladigan kodlar Muvaffaqiyat (2xx) 200 OK - hammasi joyida 201 Created - resurs yaratildi 202 Accepted - qabul qilindi, bajarilmoqda 204 No Content - muvaffaqiyat, javob yo'q Mijoz xatosi (4xx) 400 Bad Request - noto'g'ri so'rov 401 Unauthorized - kirish kerak 403 Forbidden - huquq yo'q 404 Not Found - topilmadi Server xatosi (5xx) 500 Internal Server Error 502 Bad Gateway 503 Service Unavailable Muhim boshqalar 409 Conflict - ziddiyat 422 Unprocessable - validatsiya xatosi 429 Too Many Requests - chegara 4xx - mijoz aybi · 5xx - server aybi
To'g'ri kod mijozga nima qilish kerakligini aytadi
Har doim 200 qaytarish - keng tarqalgan xato
JSON
HTTP/1.1 200 OK
{"success": false, "error": "Mahsulot topilmadi"}

Bu noto'g'ri. HTTP allaqachon xato bildirish mexanizmiga ega:

JSON
HTTP/1.1 404 Not Found
{"xato": {"kod": "mahsulot_topilmadi", "xabar": "Mahsulot topilmadi"}}

Nima uchun muhim: monitoring vositalari, proksi va mijoz kutubxonalari holat kodiga qarab ishlaydi.

401 va 403 farqi
  • 401 Unauthorized - "kim ekaningizni bilmayman" (kirish kerak)
  • 403 Forbidden - "kim ekaningizni bilaman, lekin ruxsat yo'q"

Nomlar chalkash: 401 aslida "autentifikatsiya kerak" degani.

So'rov va javob formati #

JSON
POST /api/v1/buyurtmalar
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

{
  "elementlar": [
    {"mahsulot_id": 42, "soni": 2},
    {"mahsulot_id": 17, "soni": 1}
  ],
  "manzil_id": 5,
  "tolov_usuli": "karta",
  "izoh": "Kechqurun yetkazing"
}
JSON
HTTP/1.1 201 Created
Location: /api/v1/buyurtmalar/1042
Content-Type: application/json

{
  "malumot": {
    "id": 1042,
    "raqam": "B-20260815-0042",
    "holat": "yangi",
    "jami": {"qiymat": 750000, "valyuta": "UZS"},
    "yaratilgan": "2026-08-15T14:22:31+05:00",
    "elementlar": [
      {
        "mahsulot_id": 42,
        "nomi": "Klaviatura Logitech",
        "narx": {"qiymat": 250000, "valyuta": "UZS"},
        "soni": 2,
        "summa": {"qiymat": 500000, "valyuta": "UZS"}
      }
    ]
  }
}
Javobni malumot ichiga o'rang
JSON
{"malumot": {...}}

Nima uchun? Keyinchalik meta ma'lumot qo'shish oson bo'ladi:

JSON
{
  "malumot": [...],
  "meta": {"jami": 245, "sahifa": 3},
  "havolalar": {"keyingi": "/api/v1/mahsulotlar?sahifa=4"}
}

Massivni to'g'ridan-to'g'ri qaytarsangiz, meta qo'shish uchun buzuvchi o'zgarish kerak bo'ladi.

Xatolarni qaytarish #

JSON
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "xato": {
    "kod": "validatsiya_xatosi",
    "xabar": "So'rovda xatolar bor",
    "tafsilotlar": [
      {
        "maydon": "elementlar.0.soni",
        "kod": "min_qiymat",
        "xabar": "Soni kamida 1 bo'lishi kerak"
      },
      {
        "maydon": "manzil_id",
        "kod": "topilmadi",
        "xabar": "Bunday manzil mavjud emas"
      }
    ],
    "sorov_id": "req_8f3a1d0e4b7c"
  }
}
Xato javobining tarkibi
MaydonNima uchun
kodDastur uni tekshirishi uchun (matn o'zgarishi mumkin)
xabarOdam o'qishi uchun
tafsilotlarQaysi maydonda muammo
sorov_idQo'llab-quvvatlashga murojaat qilganda

sorov_id ni jurnalga ham yozing - foydalanuvchi shu raqamni aytsa, muammoni bir zumda topasiz.

Ichki tafsilotlarni oshkor qilmang
JSON
{
  "xato": "SQLSTATE[23000]: Integrity constraint violation:
           1062 Duplicate entry '[email protected]' for key 'uq_email'
           in /var/www/app/Repozitoriy.php:142"
}

Bu hujumchiga baza tuzilmasi, fayl yo'llari va texnologiyani oshkor qiladi.

Foydalanuvchiga: "Bu email allaqachon ro'yxatdan o'tgan". Jurnalga: to'liq tafsilot.

Sahifalash #

Natija
GET /api/v1/mahsulotlar?sahifa=3&chegara=20
JSON
{
  "malumot": [...],
  "meta": {
    "jami": 245,
    "sahifa": 3,
    "chegara": 20,
    "sahifalar": 13
  },
  "havolalar": {
    "ozi":      "/api/v1/mahsulotlar?sahifa=3&chegara=20",
    "birinchi": "/api/v1/mahsulotlar?sahifa=1&chegara=20",
    "oldingi":  "/api/v1/mahsulotlar?sahifa=2&chegara=20",
    "keyingi":  "/api/v1/mahsulotlar?sahifa=4&chegara=20",
    "oxirgi":   "/api/v1/mahsulotlar?sahifa=13&chegara=20"
  }
}
Katta ma'lumotda kursor sahifalash

OFFSET 100000 juda sekin - baza 100 000 qatorni o'qib tashlab yuboradi.

Natija
GET /api/v1/hodisalar?kursor=eyJpZCI6MTA0Mn0&chegara=50
SQL
SELECT * FROM hodisalar WHERE id > 1042 ORDER BY id LIMIT 50;

Bu har doim tez ishlaydi va yangi yozuv qo'shilganda takrorlanish bo'lmaydi.

Filtrlash, saralash, tanlash #

Natija
GET /api/v1/mahsulotlar
    ?kategoriya=5
    &narx_dan=100000
    &narx_gacha=500000
    &mavjud=true
    &qidiruv=klaviatura
    &saralash=-narx,nomi
    &maydonlar=id,nomi,narx
PHP
final class MahsulotFiltri
{
    public function __construct(
        public readonly ?int $kategoriyaId = null,
        public readonly ?int $narxDan = null,
        public readonly ?int $narxGacha = null,
        public readonly ?bool $mavjud = null,
        public readonly ?string $qidiruv = null,
        public readonly array $saralash = ['id' => 'asc'],
    ) {}

    public static function sorovdan(array $parametrlar): self
    {
        return new self(
            kategoriyaId: isset($parametrlar['kategoriya'])
                ? (int) $parametrlar['kategoriya'] : null,
            narxDan: isset($parametrlar['narx_dan'])
                ? (int) $parametrlar['narx_dan'] : null,
            qidiruv: $parametrlar['qidiruv'] ?? null,
            saralash: self::saralashniTahlilQiling($parametrlar['saralash'] ?? 'id'),
        );
    }

    private static function saralashniTahlilQiling(string $satr): array
    {
        $ruxsat = ['id', 'nomi', 'narx', 'yaratilgan'];
        $natija = [];

        foreach (explode(',', $satr) as $maydon) {
            $yonalish = str_starts_with($maydon, '-') ? 'desc' : 'asc';
            $maydon = ltrim($maydon, '-+');

            if (in_array($maydon, $ruxsat, true)) {
                $natija[$maydon] = $yonalish;
            }
        }

        return $natija ?: ['id' => 'asc'];
    }
}
Saralash maydonini oq ro'yxatdan tekshiring
PHP
// SQL inyeksiya
$sql = "SELECT * FROM mahsulotlar ORDER BY {$_GET['saralash']}";

Ustun nomlarini parametrlash mumkin emas - faqat oq ro'yxat.

Autentifikatsiya #

Natija
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
UsulQachon
API kalitServer-server, oddiy holat
JWTStateless, mikroservislar
OAuth 2.0Uchinchi tomon ilovalari
Sessiya cookieBir domendagi veb-ilova
JWT ni bekor qilib bo'lmaydi

JWT server tomonda saqlanmaydi - shuning uchun uni muddatidan oldin bekor qilish mumkin emas.

Foydalanuvchi chiqsa yoki bloklansa, token muddati tugaguncha amal qiladi.

Yechimlar:

  • Qisqa muddat (15 daqiqa) + yangilash tokeni
  • Qora ro'yxat (lekin bu stateless afzalligini yo'qotadi)

Chegaralash #

Natija
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1755264000
Retry-After: 3600

{
  "xato": {
    "kod": "chegara_oshdi",
    "xabar": "Soatiga 1000 so'rov chegarasi oshdi. 1 soatdan keyin urinib ko'ring."
  }
}
Sarlavhalarni har doim qaytaring

X-RateLimit-Remaining mijozga qancha so'rov qolganini aytadi - u chegaraga yetmasdan o'zini sekinlashtira oladi.

Versiyalash #

API versiyalash usullari 1. URL da GET /api/v1/mahsulotlar Eng ko'p ishlatiladi, ko'rinadi, keshlash oson 2. Sarlavhada Accept: application/vnd.dokon.v2+json Toza URL, lekin sinash qiyinroq 3. Parametrda GET /api/mahsulotlar?version=2 Tavsiya etilmaydi - kesh bilan muammo
URL da versiyalash - eng amaliy tanlov
Nima buzuvchi o'zgarish hisoblanadi?
BuzuvchiBuzuvchi emas
Maydonni o'chirishYangi maydon qo'shish
Maydon nomini o'zgartirishYangi ixtiyoriy parametr
Maydon turini o'zgartirishYangi endpoint
Yangi majburiy parametrYangi holat kodi (hujjatlashtirilgan)
Xato formatini o'zgartirishIshlash yaxshilanishi

Postel qonuni: *"Yuborayotganingizda qat'iy, qabul qilayotganingizda bag'rikeng bo'ling."*

Idempotentlik #

Natija
POST /api/v1/buyurtmalar
Idempotency-Key: 8f3a1d0e-4b7c-4a5f-9d1e-3b6c8a0f2d4e
PHP
final class IdempotentlikOraliqQatlami
{
    public function ishlang(Sorov $sorov, callable $keyingi): Javob
    {
        $kalit = $sorov->sarlavha('Idempotency-Key');

        if ($kalit === null) {
            return $keyingi($sorov);
        }

        $saqlangan = $this->kesh->oling("idem:{$kalit}");
        if ($saqlangan !== null) {
            return $saqlangan;
        }

        $javob = $keyingi($sorov);

        if ($javob->kod() < 500) {
            $this->kesh->saqlang("idem:{$kalit}", $javob, 86400);
        }

        return $javob;
    }
}
Nima uchun kerak?

Mijoz "Buyurtma berish" tugmasini bosdi, tarmoq uzildi, javob kelmadi. U yana bosdi.

Idempotentlik kaliti bo'lmasa - ikkita buyurtma yaratiladi.

To'lov API lari uchun bu majburiy talab.

OpenAPI hujjati #

YAML
openapi: 3.0.3
info:
  title: Onlayn do'kon API
  version: 1.0.0
  description: Mahsulotlar va buyurtmalar bilan ishlash

servers:
  - url: https://api.dokon.uz/v1
    description: Ishlab chiqarish
  - url: https://sinov-api.dokon.uz/v1
    description: Sinov muhiti

paths:
  /mahsulotlar:
    get:
      summary: Mahsulotlar ro'yxati
      parameters:
        - name: kategoriya
          in: query
          schema: { type: integer }
        - name: sahifa
          in: query
          schema: { type: integer, default: 1, minimum: 1 }
      responses:
        '200':
          description: Muvaffaqiyatli
          content:
            application/json:
              schema:
                type: object
                properties:
                  malumot:
                    type: array
                    items:
                      $ref: '#/components/schemas/Mahsulot'

    post:
      summary: Yangi mahsulot yaratish
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MahsulotSorovi'
      responses:
        '201':
          description: Yaratildi
        '422':
          description: Validatsiya xatosi

components:
  schemas:
    Mahsulot:
      type: object
      required: [id, nomi, narx]
      properties:
        id:   { type: integer, example: 42 }
        nomi: { type: string, example: "Klaviatura Logitech" }
        narx:
          type: object
          properties:
            qiymat:  { type: integer, example: 250000 }
            valyuta: { type: string, example: "UZS" }

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
OpenAPI dan nima olinadi?
  1. Interaktiv hujjat (Swagger UI) - sinab ko'rish mumkin
  2. Mijoz kutubxonasi avtomatik yaratiladi (o'nlab tilda)
  3. So'rov validatsiyasi sxema asosida
  4. Soxta server frontend jamoasi uchun
  5. Avtomatik testlar sxemaga muvofiqlikni tekshiradi
Terminal
npx @redocly/cli preview-docs openapi.yaml
npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g php

REST ga muqobil #

UslubQachon
RESTUmumiy holat, ochiq API
GraphQLMijoz kerakli maydonlarni o'zi tanlaydi
gRPCXizmatlararo, yuqori ishlash
WebSocketReal vaqt, ikki tomonlama
WebhookServer mijozga xabar beradi
PHP
// Webhook yuborish
final class WebhookYuboruvchi
{
    public function yuboring(string $url, array $hodisa, string $sir): void
    {
        $tana = json_encode($hodisa, JSON_UNESCAPED_UNICODE);
        $imzo = hash_hmac('sha256', $tana, $sir);

        $this->http->post($url, [
            'sarlavhalar' => [
                'Content-Type'      => 'application/json',
                'X-Webhook-Imzo'    => $imzo,
                'X-Webhook-Hodisa'  => $hodisa['turi'],
            ],
            'tana' => $tana,
        ]);
    }
}
Webhook ni imzolang

Qabul qiluvchi xabar haqiqatan sizdan kelganini tekshira olishi kerak. Aks holda har kim soxta webhook yuborishi mumkin.

API loyihalash tekshiruv ro'yxati #

Chiqarishdan oldin
TalabBajarildi
Resurs nomlari ot va ko'plikda
HTTP metodlari to'g'ri ishlatilgan
Holat kodlari mos
Xato formati bir xil
Sahifalash amalga oshirilgan
Filtrlash oq ro'yxat bilan
Autentifikatsiya va huquq tekshiruvi
Chegaralash yoqilgan
Versiya URL da
OpenAPI hujjati yozilgan
CORS to'g'ri sozlangan
Barcha so'rovlar jurnalga yoziladi
Ichki tafsilotlar oshkor qilinmaydi
Amaliy topshiriq
  1. Blog uchun REST API endpointlarini loyihalang (postlar, izohlar, teglar).
  2. Har biri uchun HTTP metod va holat kodini yozing.
  3. Xato javob formatini belgilang va uchta misol yozing.
  4. Sahifalash bilan javob namunasini yozing.
  5. Filtr va saralash parametrlarini loyihalang.
  6. Saralash uchun oq ro'yxat tekshiruvini yozing.
  7. Idempotency-Key oraliq qatlamini yozing.
  8. OpenAPI faylini yozing (kamida 4 ta endpoint).
  9. Swagger UI da ochib ko'ring.
  10. Buzuvchi va buzuvchi bo'lmagan o'zgarishlarga 5 tadan misol yozing.

Xulosa #

  • REST - resurslarga asoslangan yondashuv; metod ma'nosini o'zgartirmang.
  • GET hech nima o'zgartirmasin - u keshlanadi va avtomatik ochiladi.
  • Resurs nomlari - ot, ko'plikda, kichik harflarda.
  • To'g'ri holat kodini qaytaring, har doim 200 emas.
  • 401 - kirish kerak, 403 - huquq yo'q.
  • Javobni malumot ichiga o'rang - kelajakda meta qo'shish uchun.
  • Xatoda kod, xabar va so'rov identifikatori bo'lsin.
  • Ichki tafsilotlarni hech qachon oshkor qilmang.
  • Katta ma'lumotda kursor sahifalash ishlating.
  • Idempotentlik kaliti takroriy amallardan himoya qiladi.
  • OpenAPI hujjatdan tashqari kod va testlar ham beradi.

Keyingi bo'limda testlash asoslarini o'rganamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.