WisarWisar
Dasturlash kitobi/13-QISM — NextJS50 daqiqa

13.6-bob: Route Handlers va Middleware

13-QISM — Next.js · 6-mavzu


1. Kirish va motivatsiya

13.5-bobda Server Actions'ni — komponentdan to'g'ridan server funksiyasini chaqirishni — o'rgandik (forma/mutation uchun ideal). Lekin ba'zan sizga haqiqiy REST API endpoint kerak bo'ladi: mobil ilova (React Native) ma'lumot so'rasa, tashqi xizmat (Stripe to'lov, GitHub) webhook yuborsa, yoki uchinchi tomon mijozi (boshqa sayt, Postman) API'ngizga murojaat qilsa — bularning hammasiga URL'li endpoint (GET /api/products, POST /api/webhook) kerak. Server Actions buni qila olmaydi (u faqat o'z Next.js komponentlaringiz uchun). Bunga — Route Handlers (route.ts) javob beradi: Next.js'ning o'rnatilgan API qatlami (Express/NestJS — 7, 8-QISM — ning Next.js ichidagi versiyasi).

Bundan tashqari, ba'zan so'rov sahifaga yetishdan oldin biror narsani qilish kerak: foydalanuvchi tizimga kirmagan bo'lsa login'ga yo'naltirish, tilni aniqlash (/uz, /en), A/B test, geolokatsiya, header qo'shish. Buni har sahifada takrorlash noqulay — Middleware (middleware.ts) buni markaziy qiladi: u har so'rovni (sahifaga yetishdan oldin) "ushlaydi" va unga ta'sir qila oladi (yo'naltirish, header, cookie). Middleware — Express middleware (7-QISM)ning Next.js, edge-darajadagi versiyasi (juda tez — foydalanuvchiga yaqin serverda ishlaydi).

Bu bob: Route Handlers (route.ts — REST API), HTTP metodlar (GET/POST/PUT/PATCH/DELETE), Request/Response (Web standart — NextRequest/NextResponse), so'rovni o'qish (body, query, header, cookie), dinamik handler ([id]), Route Handlers vs Server Actions (qachon qaysi), CORS, Middleware (middleware.ts — so'rov ushlash), middleware holatlari (auth, redirect, i18n, A/B), matcher (qaysi yo'llar), edge runtime, va caching. Bu mavzular to'liq — har kod misolida maqsad + izoh + "nima qiladi" bilan — ochib beriladi.

O'xshatish: Route Handler va Middleware — bu binoning qabulxonasi va xavfsizlik posti. Route Handler (route.ts) — bu qabulxona (reception desk): tashqaridan kelgan har kim (mobil ilova, webhook, boshqa sayt) shu yerga murojaat qiladi ("menga mahsulotlar ro'yxati kerak" = GET /api/products), va qabulxona javob beradi (JSON). Bu — binoning rasmiy kirish nuqtasi (har kim foydalana oladi — universal til: HTTP/JSON). Middleware (middleware.ts) — bu xavfsizlik posti (eshik oldidagi qorovul): har bir kishi (so'rov) binoga (sahifaga) kirishdan oldin posdan o'tadi — qorovul tekshiradi ("propuskingiz bormi?" = autentifikatsiya), kerak bo'lsa boshqa joyga yo'naltiradi ("bu xona u yerda" = redirect), yoki belgi qo'yadi ("mehmon" = header). Ya'ni Middleware — har so'rov birinchi uchraydigan nuqta (sahifaga yetishdan oldin), Route Handler — tashqi dunyo bilan rasmiy muloqot nuqtasi.

Nega muhim?

  • Haqiqiy API — mobil ilova, webhook, tashqi mijoz uchun REST endpoint (Server Actions qila olmaydi).
  • Markaziy so'rov nazorati — Middleware bilan auth/redirect/i18n bir joyda (har sahifada takror yo'q).
  • Express/NestJS o'rnini qoplash — kichik-o'rta loyihada alohida backend kerak bo'lmasligi mumkin.
  • Edge tezlik — Middleware foydalanuvchiga yaqin (juda tez — global).

2. Nazariya — chuqur tushuntirish

2.1. Route Handlers — REST API endpoint

text
  ROUTE HANDLER — route.ts faylda HTTP metod funksiyalari (REST API):

  // app/api/products/route.ts  /api/products endpoint
  export async function GET() {
    const products = await db.product.findMany();
    return Response.json(products);   // JSON javob (Web standart Response)
  }

  export async function POST(request: Request) {
    const body = await request.json();          // so'rov tanasini o'qi
    const product = await db.product.create({ data: body });
    return Response.json(product, { status: 201 });   // 201 Created
  }

  PAPKA STRUKTURASI (page.tsx kabi, lekin route.ts):
  app/api/products/route.ts        /api/products       (GET, POST)
  app/api/products/[id]/route.ts   /api/products/42     (GET, PUT, DELETE — 2.5)
  app/api/webhook/route.ts         /api/webhook         (POST — tashqi xizmat)

   route.ts — HTTP metod funksiyalari (GET/POST/...) export qiladi — REST API endpoint
   page.tsx (sahifa) va route.ts (API) — BIR papkada BIRGA bo'la olmaydi (biri yoki ikkinchisi)

Route Handlers — REST API endpoint — Next.js'ning o'rnatilgan API qatlami. Route Handlerroute.ts faylda HTTP metod funksiyalarini (GET, POST, PUT, PATCH, DELETE) export qilish — bu REST API endpoint yaratadi (Express/NestJS — 7, 8-QISM — ning Next.js versiyasi). Misol: app/api/products/route.ts /api/products endpoint; ichida export async function GET() { ... return Response.json(products) } (GET so'rovga javob — JSON) va export async function POST(request) { const body = await request.json(); ... } (POST — yangi yaratish). Papka strukturasi page.tsx kabi (13.2 — fayl-asosli), lekin route.ts: app/api/products/route.ts /api/products, app/api/products/[id]/route.ts /api/products/42 (dinamik — 2.5), app/api/webhook/route.ts /api/webhook (webhook). Javob — Response.json() (Web standart Response obyekti — 9-QISM Node.js'dagi kabi, lekin platforma-mustaqil). Ikki nuqta: (1) route.ts — HTTP metod funksiyalarini export qiladi (GET/POST/... — har biri o'sha metodga javob) — REST API endpoint; (2) page.tsx (sahifa) va route.ts (API) bir papkada birga bo'la olmaydi (bir papka yo sahifa, yo API — ikkalasi bir vaqtda emas). Route Handlers — tashqi dunyo (mobil, webhook, boshqa mijoz) bilan muloqot uchun (Server Actions o'z komponentlar uchun — farq 2.6).

2.2. HTTP metodlar (GET, POST, PUT, PATCH, DELETE)

text
  HER HTTP METOD — alohida funksiya (REST konvensiyasi — 7-QISM):

  // app/api/posts/[id]/route.ts
  export async function GET(req, { params }) {     // O'QISH (bitta post)
    const { id } = await params;
    return Response.json(await db.post.findUnique({ where: { id } }));
  }
  export async function PUT(req, { params }) {     // TO'LIQ YANGILASH
    const { id } = await params;
    const body = await req.json();
    return Response.json(await db.post.update({ where: { id }, data: body }));
  }
  export async function PATCH(req, { params }) {   // QISMAN YANGILASH
    // faqat berilgan maydonlar
  }
  export async function DELETE(req, { params }) {  // O'CHIRISH
    const { id } = await params;
    await db.post.delete({ where: { id } });
    return new Response(null, { status: 204 });   // 204 No Content
  }

  METOD MA'NOLARI (REST — 7-QISM):
  GET — o'qish | POST — yaratish | PUT — to'liq yangilash
  PATCH — qisman yangilash | DELETE — o'chirish

   Har HTTP metod — alohida export funksiya (GET/POST/PUT/PATCH/DELETE)
   Status kodlar: 200 OK, 201 Created, 204 No Content, 400/404/500 (REST — 7-QISM)

HTTP metodlar — REST API konvensiyasi (7-QISM'ning Next.js'dagi qo'llanishi). Route Handler'da har HTTP metod alohida export funksiya: GET (o'qish — ma'lumot olish), POST (yaratish — yangi resurs), PUT (to'liq yangilash — butun resursni almashtirish), PATCH (qisman yangilash — faqat ba'zi maydonlar), DELETE (o'chirish). Misol: app/api/posts/[id]/route.tsda GET (bitta post o'qish), PUT (to'liq yangilash), PATCH (qisman), DELETE (o'chirish) — har biri o'sha HTTP metodga javob beradi. Bu — REST API'ning standart strukturasi (7-QISM — Express'dagi router.get/router.post — ning Next.js fayl-asosli versiyasi: alohida route emas, balki bir faylda metod funksiyalari). Status kodlar muhim (HTTP semantikasi — 7-QISM): 200 OK (muvaffaqiyat), 201 Created (yaratildi), 204 No Content (o'chirildi — javob tanasi yo'q), 400 Bad Request (noto'g'ri so'rov), 404 Not Found (topilmadi), 500 Internal Server Error (server xatosi). Ikki nuqta: (1) har HTTP metod — alohida export funksiya (GET/POST/PUT/PATCH/DELETE — bir faylda, har biri o'z metodiga); (2) status kodlarni to'g'ri ishlat (201 yaratishda, 204 o'chirishda, 404 topilmaganda — REST semantikasi — mijoz to'g'ri tushunsin). Bu — professional REST API'ning asosi (HTTP metodlar va status kodlar — universal til, har mijoz tushunadi).

2.3. Request va Response (Web standart)

text
  REQUEST / RESPONSE — Web platforma standarti (NextRequest/NextResponse — kengaytma):

  SO'ROVNI O'QISH (Request — Web standart):
  export async function POST(request: Request) {
    const body = await request.json();           // JSON tana
    // const text = await request.text();         // matn tana
    // const form = await request.formData();      // forma tana
    const url = new URL(request.url);
    const query = url.searchParams.get("filter"); // ?filter=... (query param)
    const auth = request.headers.get("authorization"); // header
  }

  JAVOB QAYTARISH (Response — Web standart):
  return Response.json({ data });                  // JSON (eng keng)
  return Response.json({ error: "..." }, { status: 400 });  // status bilan
  return new Response("Matn", { status: 200, headers: { "Content-Type": "text/plain" } });

  NEXTREQUEST/NEXTRESPONSE (Next.js kengaytmasi — qo'shimcha qulaylik):
  import { NextRequest, NextResponse } from "next/server";
  // NextRequest: req.cookies.get(), req.nextUrl (qulayroq)
  // NextResponse: NextResponse.json(), NextResponse.redirect() (qulayroq)

   Request/Response — Web standart (platforma-mustaqil; Node, edge, brauzer bir xil)
   NextRequest/NextResponse — Next.js qo'shimcha qulaylik (cookies, redirect — ayniqsa middleware'da)

Request va Response (Web standart) — Route Handlers'ning asosidagi platforma standarti. Route Handlers Web platforma standartini (Request/Response — brauzer, Node.js, edge — hammasida bir xil — 9-QISM fetch API'dagi obyektlar) ishlatadi. So'rovni o'qish (Request): await request.json() (JSON tana), await request.text() (matn), await request.formData() (forma), new URL(request.url).searchParams.get("filter") (query param — ?filter=...), request.headers.get("authorization") (header). Javob qaytarish (Response): Response.json({ data }) (JSON — eng keng), Response.json({ error }, { status: 400 }) (status bilan), new Response("Matn", { headers: {...} }) (matn yoki boshqa format). Bundan tashqari, Next.js NextRequest/NextResponse (next/server'dan) — Web standartining kengaytmasi (qo'shimcha qulaylik): NextRequestda req.cookies.get() (cookie qulay), req.nextUrl (URL qulay); NextResponseda NextResponse.json(), NextResponse.redirect() (yo'naltirish qulay — ayniqsa middleware'da — 2.7). Ikki nuqta: (1) Request/Response — Web standart (platforma-mustaqil — Node, edge, brauzer'da bir xil — bu bilim har joyda ishlaydi, faqat Next.js'da emas); (2) NextRequest/NextResponse — Next.js qo'shimcha qulaylik (cookies, redirect — ayniqsa middleware'da qulay — 2.7). Web standartni ishlatish — Next.js'ning "platformaga yaqin" falsafasi (maxsus API o'rniga standart — bilim ko'chib yuradi). Route Handlers — standart Request/Response, qulaylik kerak bo'lganda NextRequest/NextResponse.

text
  SO'ROV MA'LUMOTLARINI O'QISH (4 manba):

  // 1. BODY (so'rov tanasi — POST/PUT):
  const body = await request.json();              // { title: "...", price: 100 }

  // 2. QUERY PARAMS (URL ?key=value):
  const { searchParams } = new URL(request.url);
  const page = searchParams.get("page") ?? "1";   // /api/posts?page=2  "2"
  const limit = searchParams.get("limit") ?? "10";

  // 3. HEADERS (so'rov sarlavhalari):
  const token = request.headers.get("authorization");  // "Bearer xxx"
  const contentType = request.headers.get("content-type");

  // 4. COOKIES (NextRequest yoki cookies()):
  import { cookies } from "next/headers";
  const cookieStore = await cookies();
  const session = cookieStore.get("session")?.value;

  // DINAMIK PARAMS (URL segmenti — [id] — 2.5):
  export async function GET(req, { params }) { const { id } = await params; }

   4 manba: body (tana), query (?key=), headers (sarlavha), cookies (cookie)
   params (URL segmenti — [id]) — 2-argument { params } orqali (2.5)

So'rovni o'qish — Route Handler'da kelgan ma'lumotlarni olish (4 manba). So'rov ma'lumoti to'rt joydan keladi: (1) body (so'rov tanasi — POST/PUT/PATCH): await request.json() (JSON — eng keng), yoki .text()/.formData() — bu yuborilgan ma'lumot (yangi mahsulot, yangilanish); (2) query params (URL'dagi ?key=value): new URL(request.url).searchParams.get("page") — masalan /api/posts?page=2&limit=10 (sahifalash, filtr, saralash — 2-bobda useSearchParamsning server tomoni); (3) headers (so'rov sarlavhalari): request.headers.get("authorization") (token — autentifikatsiya), content-type (format) — metama'lumot; (4) cookies: cookies() (next/headers'dan — Next.js 15 async) yoki NextRequest.cookies.get() — sessiya, til afzalligi. Va dinamik params (URL segmenti — [id]): GET(req, { params }) — ikkinchi argument { params } orqali 2.5-bob. Ikki nuqta: (1) 4 manba — body (yuborilgan ma'lumot), query (?key= — filtr/sahifalash), headers (token/format), cookies (sessiya); (2) params (URL segmenti — [id]) — 2-argument { params } orqali 2.5-bob. Har manba o'z maqsadiga: body (asosiy ma'lumot), query (parametrlar), header (autentifikatsiya/meta), cookie (sessiya), params (resurs identifikatori). Bu — REST API'ning kirish ma'lumotini to'liq olish usuli (Express'dagi req.body/req.query/req.headers/req.paramsning Next.js, Web-standart versiyasi — 7-QISM).

2.5. Dinamik Route Handler ([id])

text
  DINAMIK ROUTE HANDLER — [id] segmenti (resurs identifikatori — REST):

  // app/api/products/[id]/route.ts  /api/products/42
  export async function GET(
    request: Request,
    { params }: { params: Promise<{ id: string }> }   //  2-argument — dinamik params
  ) {
    const { id } = await params;                       // /api/products/42  id = "42"
    const product = await db.product.findUnique({ where: { id } });
    if (!product) {
      return Response.json({ error: "Topilmadi" }, { status: 404 });   // 404
    }
    return Response.json(product);
  }

  REST RESURS NAQSHI (to'liq):
  GET    /api/products       ro'yxat       (route.ts — GET)
  POST   /api/products       yaratish      (route.ts — POST)
  GET    /api/products/42    bitta         ([id]/route.ts — GET)
  PUT    /api/products/42    yangilash     ([id]/route.ts — PUT)
  DELETE /api/products/42    o'chirish     ([id]/route.ts — DELETE)

   [id] dinamik segment  params (2-argument); 404 topilmasa (REST semantika)
   Collection (/products) va item (/products/[id]) — REST resurs naqshi

Dinamik Route Handler ([id]) — resurs identifikatori bilan API (REST naqshi). Dinamik segment ([id] — 13.2: 2.2 — sahifa uchun ko'rganmiz, endi API uchun): app/api/products/[id]/route.ts /api/products/42. Handler funksiyasi ikki argument oladi: request (so'rov) va { params } (dinamik segmentlar — 2-argument): const { id } = await params (/api/products/42 id = "42" — Next.js 15: async — 13.2: 2.2). Topilmaganda 404 qaytarish muhim (Response.json({ error }, { status: 404 }) — REST semantikasi — mijoz "yo'q" ekanini biladi). Bu — to'liq REST resurs naqshi: collection (/api/productsroute.ts: GET ro'yxat, POST yaratish) va item (/api/products/[id][id]/route.ts: GET bitta, PUT yangilash, DELETE o'chirish) — har biri o'z faylda (collection va item alohida papka). Ikki nuqta: (1) [id] dinamik segment params (2-argument — await params); topilmaganda 404 (REST semantika — to'g'ri status); (2) collection (/products) va item (/products/[id]) — REST resurs naqshi (standart struktura — har RESTful API shunday). Bu — Express'dagi router.get("/products/:id")ning Next.js fayl-asosli versiyasi (route massiv emas, papka strukturasi). Dinamik Route Handler — har resurs (mahsulot, foydalanuvchi, post)ning individual endpoint'i (CRUD — 7-QISM).

2.6. Route Handlers vs Server Actions (qachon qaysi)

text
  QACHON QAYSI — Route Handler yoki Server Action (muhim qaror):

  ┌─────────────────────────────┬──────────────────────────────┐
  │ ROUTE HANDLER (route.ts)    │ SERVER ACTION ("use server") │
  ├─────────────────────────────┼──────────────────────────────┤
  │  Tashqi mijoz (mobil app)  │  O'z Next.js komponentlari   │
  │  Webhook (Stripe, GitHub)  │  Forma/mutation 13.5-bob       │
  │  Uchinchi tomon API        │  Progressive enhancement     │
  │  Public REST API           │  useOptimistic/useActionState│
  │  GET (ma'lumot berish)      │  Soddaroq (API yozish yo'q)  │
  │  Standart HTTP kerak       │  Type-safe (to'g'ridan import)│
  └─────────────────────────────┴──────────────────────────────┘

  ODDIY QOIDA:
   O'z ilovangiz ichida mutation (forma)  SERVER ACTION (soddaroq — 13.5)
   Tashqaridan murojaat (mobil, webhook, boshqa sayt)  ROUTE HANDLER (REST)
   GET ma'lumot (Server Component'da)  to'g'ridan await (ikkalasi ham emas — 13.5: 2.1)

   Server Action — o'z komponentlar (forma/mutation); Route Handler — tashqi mijoz (REST API)
   Server Component'da ma'lumot OLISH — to'g'ridan await (Route Handler ham, Action ham shart emas)

Route Handlers vs Server Actions — muhim qaror (qachon qaysi). Ikki usul ham server'da ishlaydi, lekin maqsadlari farq: Route Handler (route.ts): tashqi mijoz (mobil ilova — React Native), webhook (Stripe to'lov, GitHub push — tashqi xizmat POST yuboradi), uchinchi tomon API, public REST API, standart HTTP kerak bo'lganda — ya'ni tashqi dunyo bilan muloqot. Server Action ("use server"): o'z Next.js komponentlaringiz uchun forma/mutation 13.5-bob, progressive enhancement, useOptimistic/useActionState, soddaroq (alohida API yozish yo'q), type-safe (to'g'ridan import — TypeScript) — ya'ni o'z ilova ichidagi mutation. Oddiy qoida: (1) o'z ilovangiz ichida mutation (forma yuborish) Server Action (soddaroq — 13.5); (2) tashqaridan murojaat (mobil, webhook, boshqa sayt) Route Handler (REST — universal HTTP); (3) Server Component'da ma'lumot olish (GET) to'g'ridan await (13.5: 2.1 — Route Handler ham, Action ham shart emas — to'g'ridan DB/fetch). Ikki nuqta: (1) Server Action — o'z komponentlar (forma/mutation — soddaroq); Route Handler — tashqi mijoz (REST API — universal); (2) Server Component'da ma'lumot olish — to'g'ridan await (ikkalasini ham ishlatma — keraksiz qatlam). Keng xato: o'z formangiz uchun Route Handler yozib (API + client fetch), keyin Server Action'ning soddaligini o'tkazib yuborish. To'g'ri tanlov: ichki Server Action, tashqi Route Handler. Bu — Next.js backend qatlamini to'g'ri tashkil qilishning kaliti.

2.7. Middleware — so'rovni ushlash

text
  MIDDLEWARE — har so'rovni SAHIFAGA YETISHDAN OLDIN ushlaydi (markaziy nazorat):

  // middleware.ts (LOYIHA ILDIZIDA — app'ning yonida)
  import { NextRequest, NextResponse } from "next/server";

  export function middleware(request: NextRequest) {
    // Har so'rov BU YERDAN o'tadi (sahifaga yetishdan oldin):
    const token = request.cookies.get("token")?.value;

    // Misol: himoyalangan yo'l + token yo'q  login'ga:
    if (request.nextUrl.pathname.startsWith("/dashboard") && !token) {
      return NextResponse.redirect(new URL("/login", request.url));  // yo'naltir
    }

    return NextResponse.next();   //  davom ettir (sahifaga o'tsin)
  }

  // QAYSI YO'LLAR (matcher — 2.8):
  export const config = { matcher: ["/dashboard/:path*"] };

  MIDDLEWARE OQIMI:
  So'rov  MIDDLEWARE (tekshir/o'zgartir)  [next()  sahifa] yoki [redirect  boshqa]

   middleware.ts — har so'rov sahifaga yetishdan OLDIN o'tadi (auth, redirect, header)
   NextResponse.next() (davom) | .redirect() (yo'naltir) | .rewrite() (yashirin)

Middleware — so'rovni ushlash — har so'rovni markaziy nuqtada boshqarish. Middlewaremiddleware.ts faylda (loyiha ildizida — app/ yonida), har so'rovni sahifaga yetishdan oldin "ushlaydi". Funksiya: export function middleware(request: NextRequest) { ... } — har so'rov shu funksiyadan o'tadi (sahifa/Route Handler render bo'lishidan oldin). Ichida request.cookies.get("token") (cookie o'qish), request.nextUrl.pathname (joriy yo'l), va qaror: NextResponse.redirect(...) (yo'naltirish — masalan himoyalangan /dashboardga token'siz kirsa login'ga), yoki NextResponse.next() (davom ettirish — sahifaga o'tsin), yoki NextResponse.rewrite(...) (yashirin — URL o'zgarmaydi, lekin boshqa kontent). config.matcher 2.8-bob — middleware qaysi yo'llarga ishlashini belgilaydi. Oqim: so'rov middleware (tekshir/o'zgartir) next() (sahifaga) yoki redirect (boshqa joyga). Middleware Express middleware (7-QISM)ning Next.js, edge-darajadagi versiyasi (har so'rovdan oldin ishlaydi — markaziy). Ikki nuqta: (1) middleware.ts — har so'rov sahifaga yetishdan oldin o'tadi (auth, redirect, header — markaziy, har sahifada takror yo'q); (2) NextResponse.next() (davom), .redirect() (yo'naltir), .rewrite() (yashirin — URL saqlab boshqa kontent). Middleware — so'rov hayot siklining eng birinchi nuqtasi (foydalanuvchiga yaqin edge serverda — 2.9 — juda tez). Bu — global so'rov nazoratining (auth, til, A/B) ideal joyi.

2.8. Middleware holatlari va matcher

text
  MIDDLEWARE QO'LLANILISHI (keng holatlar):

  1. AUTH GUARD — himoyalangan yo'l (token tekshir  login'ga — 2.7)
  2. I18N — til aniqlash (/uz, /en — geolokatsiya yoki header'dan):
     if (!pathname.startsWith("/uz") && !pathname.startsWith("/en"))
       return NextResponse.redirect(new URL(`/uz${pathname}`, request.url));
  3. A/B TEST — foydalanuvchilarni guruhlash (cookie bilan variant A yoki B)
  4. HEADER QO'SHISH — xavfsizlik header'lari (CSP, X-Frame-Options — 14-QISM)
  5. BOT/RATE LIMIT — so'rovni filtrlash (IP bo'yicha)

  MATCHER — middleware QAYSI yo'llarga ishlashi (performance — keraksizga ishlamasin):
  export const config = {
    matcher: [
      "/dashboard/:path*",     // /dashboard va ostidagilar
      "/api/:path*",           // barcha API
      "/((?!_next/static|favicon.ico).*)",  // statik fayllar bundan tashqari
    ],
  };

   Middleware: auth, i18n, A/B, header, rate limit (markaziy so'rov nazorati)
   matcher — qaysi yo'llar (keraksiz so'rovga ishlamasin — performance; statikni chiqar)

Middleware holatlari va matcher — middleware'ning keng qo'llanishi va nishonlash. Qo'llanilishi (keng holatlar): (1) auth guard — himoyalangan yo'l (token tekshirib, login'ga yo'naltirish — 2.7 — markaziy, har sahifada guard yozish o'rniga); (2) i18n (xalqarolashtirish) — til aniqlash (/uz, /en — agar til prefiksi yo'q bo'lsa, geolokatsiya yoki Accept-Language header'dan aniqlab yo'naltirish); (3) A/B test — foydalanuvchilarni guruhlash (cookie bilan — yarmiga variant A, yarmiga B — marketing); (4) header qo'shish — xavfsizlik header'lari (CSP, X-Frame-Options — 14-QISM — har javobga); (5) bot/rate limit — so'rovni filtrlash (IP bo'yicha cheklash — DDoS himoya). matcher (config.matcher) — middleware qaysi yo'llarga ishlashini belgilaydi (performance — middleware har so'rovda ishlaydi, shuning uchun keraksiz yo'llarga — masalan statik fayllar, rasm — ishlamasin): matcher: ["/dashboard/:path*", "/api/:path*"] (faqat dashboard va API), yoki regex bilan statikni chiqarib tashlash ((?!_next/static|favicon.ico)). Ikki nuqta: (1) middleware — auth, i18n, A/B, header, rate limit (markaziy so'rov nazorati — har joyda takrorlamasdan); (2) matcher — qaysi yo'llarga ishlasin (keraksiz so'rovga — statik, rasm — ishlamasin — performance muhim, chunki middleware har so'rovni sekinlashtirishi mumkin). Middleware kuchli, lekin har so'rovda ishlagani uchun yengil va nishonlangan (matcher) bo'lishi kerak. Bu — global so'rov logikasining (kim, qaerga, qanday) markaziy joyi.

2.9. Edge runtime va Node.js runtime

text
  IKKI RUNTIME — kod QAYERDA va QANDAY ishlaydi (Route Handler/Middleware):

  EDGE RUNTIME (default middleware — foydalanuvchiga YAQIN, tez, yengil):
   global tarqalgan serverlar (CDN kabi — foydalanuvchiga eng yaqin)
   juda tez ishga tushadi (cold start yo'q); lekin CHEKLANGAN (Node.js API'ning bir qismi)
   Web standart API (fetch, Request, Response — Node 'fs', 'crypto' to'liq emas)

  NODE.JS RUNTIME (Route Handler default — to'liq Node.js):
   to'liq Node.js (fs, crypto, DB drayverlar, har qanday npm paket)
   bir oz sekinroq ishga tushadi; lekin TO'LIQ imkoniyat

  TANLASH (Route Handler'da):
  export const runtime = "edge";    // edge (tez, yengil — oddiy so'rov)
  export const runtime = "nodejs";  // Node.js (DB, og'ir paket — default)

  ┌────────────────────────────────────────────────────────────┐
  │ Edge: tez, global, yengil (cheklangan) | Node: to'liq (DB)  │
  │ Middleware  edge (default); Route Handler  nodejs (default)│
  └────────────────────────────────────────────────────────────┘

   Edge — foydalanuvchiga yaqin, tez (lekin cheklangan API); Node — to'liq (DB, og'ir)
   Middleware edge'da (tez); DB kerak Route Handler nodejs'da (Prisma — edge'da cheklangan)

Edge runtime va Node.js runtime — kod qaerda va qanday ishlashi (ikki muhit). Next.js'da kod ikki runtime'da ishlashi mumkin: (1) Edge runtime (middleware default) — kod global tarqalgan serverlarda (CDN kabi — foydalanuvchiga eng yaqin geografik nuqtada) ishlaydi: juda tez ishga tushadi (cold start yo'q — har doim tayyor), yengil, lekin cheklangan (faqat Web standart API — fetch, Request, Response — Node.js'ning fs, to'liq crypto, DB drayverlari to'liq emas); (2) Node.js runtime (Route Handler default) — to'liq Node.js (har qanday npm paket, fs, crypto, DB drayverlari — Prisma, og'ir kutubxonalar): bir oz sekinroq ishga tushadi, lekin to'liq imkoniyat. Tanlash: export const runtime = "edge" (edge — tez, yengil — oddiy so'rov, auth tekshirish) yoki export const runtime = "nodejs" (to'liq — DB, og'ir paket — default Route Handler uchun). Ikki nuqta: (1) edge — foydalanuvchiga yaqin, tez (lekin API cheklangan), Node — to'liq (DB, og'ir kutubxona); (2) middleware edge'da (tez — har so'rovda ishlaydi, yengil bo'lishi kerak — shuning uchun edge), DB kerak bo'lsa Route Handler nodejs'da (Prisma kabi ORM edge'da to'liq ishlamaydi — DB ulanishi Node kerak). Demak: tez, oddiy, foydalanuvchiga yaqin ish (auth tekshirish, redirect) edge (middleware); og'ir, DB, to'liq Node ish nodejs (Route Handler). Bu — Next.js'ning global deploy (Vercel edge network — 13.11)ning asosi (kod foydalanuvchiga yaqin ishlaydi — kechikish kam).

2.10. CORS, caching va best practices

text
  CORS — boshqa domendan so'rovga ruxsat (tashqi mijoz uchun Route Handler'da):
  export async function GET() {
    return Response.json(data, {
      headers: {
        "Access-Control-Allow-Origin": "*",          // har domendan (yoki aniq domen)
        "Access-Control-Allow-Methods": "GET, POST",
      },
    });
  }
  // OPTIONS (preflight) ham kerak bo'lishi mumkin (brauzer tekshiruvi)

  CACHING (Route Handler — 13.4 kabi):
  export const revalidate = 3600;   // GET javobini 1 soat keshla (ISR kabi)
  export const dynamic = "force-dynamic";  // har so'rovda yangi

  BEST PRACTICES:
   Route Handler — tashqi mijoz; Server Action — o'z forma 2.6-bob
   Validatsiya (Zod) + status kodlar (400/404/500 — 2.2)
   Middleware yengil (edge — tez; matcher bilan nishonla — 2.8)
   DB kerak  Route Handler nodejs (edge emas — 2.9)
   Xavfsizlik header'lari middleware'da (CSP — 14-QISM)
   Webhook'da imzo tekshir (Stripe signature — xavfsizlik)

   CORS — tashqi domen so'rovga ruxsat (Access-Control header'lari)
   Best: Route Handler tashqiga, validatsiya+status, middleware yengil, webhook imzo

CORS, caching va best practices — Route Handlers/Middleware'ni professional ishlatish. CORS (Cross-Origin Resource Sharing — 7-QISM) — boshqa domendan (masalan app.com'dan api.com'ga) so'rovga ruxsat: Route Handler javobiga Access-Control-Allow-Origin header ("*" — har domen, yoki aniq domen — xavfsizroq) va Access-Control-Allow-Methods qo'shish; ba'zan OPTIONS metod (preflight — brauzer dastlabki tekshiruvi) ham kerak. Bu — public API yoki boshqa frontend'dan murojaat uchun (o'z Next.js sahifangizdan so'rovda CORS kerak emas — bir domen). Caching (Route Handler — 13.4 kabi): export const revalidate = 3600 (GET javobini keshlash — ISR kabi), export const dynamic = "force-dynamic" (har so'rovda yangi). Best practices: (1) Route Handler — tashqi mijoz, Server Action — o'z forma 2.6-bob; (2) validatsiya (Zod) + to'g'ri status kodlar (400/404/500 — 2.2); (3) middleware yengil (edge — tez, matcher bilan nishonlash — 2.8); (4) DB kerak Route Handler nodejs (edge emas — 2.9); (5) xavfsizlik header'lari middleware'da (CSP, X-Frame — 14-QISM); (6) webhook'da imzo tekshir (Stripe signature — webhook haqiqatan Stripe'dan kelganini tasdiqlash — soxta webhook'dan himoya — xavfsizlik). Ikki nuqta: (1) CORS — tashqi domen so'rovga ruxsat (Access-Control header'lari — public API uchun); (2) best: Route Handler tashqiga, validatsiya+status, middleware yengil, webhook imzo. Bu — Next.js backend qatlamining (API + so'rov nazorat) professional yakuni. Route Handlers va Middleware — Next.js'ning full-stack imkoniyatlarini to'ldiradi (Server Actions ichki, Route Handlers tashqi, Middleware global).

2.11. OPTIONS, HEAD va dinamik vs statik Route Handler

text
  OPTIONS (CORS preflight) va HEAD — qo'shimcha HTTP metodlar:

  // OPTIONS — brauzer "preflight" so'rovi (murakkab CORS so'rovdan OLDIN):
  export async function OPTIONS() {
    return new Response(null, {
      status: 204,                              // No Content
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type, Authorization",
      },
    });
  }

  // HEAD — GET kabi, lekin FAQAT header (tana yo'q — mavjudlik/hajm tekshirish):
  export async function HEAD() {
    return new Response(null, { headers: { "X-Total-Count": "42" } });
  }

  DINAMIK vs STATIK ROUTE HANDLER (GET keshlanadimi):
   GET (parametrsiz, statik)  NEXT KESHLAYDI (build vaqtida — bir marta)
   dinamik bo'lsa (request/searchParams/cookies ishlatsa)  HAR so'rovda yangi
   majburiy dinamik: export const dynamic = "force-dynamic";
   POST/PUT/DELETE — HECH QACHON keshlanmaydi (mutation)

   OPTIONS — CORS preflight (brauzer avtomatik yuboradi); HEAD — faqat header
   GET statik  keshlanadi; force-dynamic yoki request o'qish  har so'rovda yangi

OPTIONS, HEAD va dinamik vs statik Route Handler — HTTP metodlarning to'liq to'plami va keshlash xatti-harakati. Route Handler GET/POST/PUT/PATCH/DELETE'dan tashqari yana ikki metodni qo'llab-quvvatlaydi: (1) OPTIONS — brauzer preflight so'rovi. Boshqa domenga "murakkab" so'rov (masalan Authorization header yoki PUT/DELETE bilan) yuborishdan oldin, brauzer avtomatik OPTIONS so'rovini yuboradi ("bu so'rovga ruxsat bormi?" — 2.10 CORS). Server Access-Control-Allow-* header'lari bilan 204 qaytaradi (ruxsat berildi), keyin brauzer asosiy so'rovni yuboradi. Public API'da (boshqa domendan PUT/DELETE kelsa) OPTIONS handler majburiy; (2) HEADGET kabi, lekin faqat header (javob tanasi yo'q) — resurs mavjudligini yoki hajmini (Content-Length, X-Total-Count) tekshirish uchun (fayl yuklashdan oldin hajm bilish). Dinamik vs statik: Next.js GET handler'ni statik deb hisoblaydi (build vaqtida bir marta bajarib, natijani keshlaydi) — agar u request/searchParams/cookies/headers ishlatmasa. Agar ishlatsa (masalan new URL(request.url).searchParams) — handler avtomatik dinamik bo'ladi (har so'rovda qayta bajariladi). Majburiy dinamik qilish: export const dynamic = "force-dynamic" (masalan har doim yangi ma'lumot kerak bo'lsa). POST/PUT/DELETE hech qachon keshlanmaydi (mutation — har doim bajariladi). Ikki nuqta: (1) OPTIONS — CORS preflight (brauzer avtomatik — public API'da kerak), HEAD — faqat header (mavjudlik/hajm); (2) GET statik keshlanadi (tez), lekin request/searchParams/cookies o'qisa yoki force-dynamic bo'lsa har so'rovda yangi (13.4 rendering falsafasi API darajasida). Bu — Route Handler keshlash xatti-harakatini to'liq nazorat qilish (statik = tez, dinamik = har doim yangi).

2.12. Rate limiting va Next API vs alohida backend

text
  RATE LIMITING — so'rovlar sonini cheklash (DDoS/abuse himoya — Upstash misoli):

  // lib/ratelimit.ts — Upstash Redis (edge'da ishlaydi — middleware uchun):
  import { Ratelimit } from "@upstash/ratelimit";
  import { Redis } from "@upstash/redis";
  const ratelimit = new Ratelimit({
    redis: Redis.fromEnv(),
    limiter: Ratelimit.slidingWindow(10, "10 s"),   // 10 so'rov / 10 soniya
  });

  // middleware.ts yoki Route Handler ichida:
  const ip = request.headers.get("x-forwarded-for") ?? "anon";
  const { success } = await ratelimit.limit(ip);
  if (!success) return new Response("Juda ko'p so'rov", { status: 429 });  // 429

  QACHON NEXT API YETARLI, QACHON ALOHIDA BACKEND (08-QISM — NestJS):
   Next Route Handlers YETARLI: kichik-o'rta loyiha, frontend bilan bitta deploy,
    oddiy CRUD/webhook/BFF, jamoa Next.js'ni biladi
   ALOHIDA BACKEND (NestJS — 08-QISM) KERAK: murakkab domen (ko'p modul, DI, guards),
    bir nechta mijoz (web+mobil+admin bitta API), og'ir fon vazifalar (queue, cron),
    mikroservis, backend jamoasi alohida, til/texnologiya farqi

   Rate limit — 429 status (Upstash edge'da; IP bo'yicha oyna)
   Next API — kichik-o'rta/BFF; alohida NestJS — murakkab domen/ko'p mijoz/og'ir fon

Rate limiting va Next API vs alohida backend — himoya qatlami va arxitektura qarori. Rate limiting (so'rovlar sonini cheklash) — bir mijoz (IP) qisqa vaqtda juda ko'p so'rov yuborishining oldini oladi (DDoS, brute-force login, API abuse himoyasi). Edge middleware'da ishlashi uchun holatni tashqarida saqlash kerak (edge serverlar tarqoq — xotira ulashilmaydi), shuning uchun Upstash Redis (serverless Redis — edge'ga mos, HTTP orqali) keng ishlatiladi: Ratelimit.slidingWindow(10, "10 s") (har IP uchun 10 soniyada 10 so'rov), ratelimit.limit(ip) chegaradan oshsa success: false — server 429 Too Many Requests qaytaradi. Buni middleware'da (barcha API'ga) yoki alohida Route Handler'da (masalan login endpoint) qo'llash mumkin. Next API yetarli, qachon alohida backend (08-QISM — NestJS — muhim arxitektura qarori): Next Route Handlers yetarli — kichik-o'rta loyiha, frontend bilan bitta deploy (bitta repo, bitta Vercel), oddiy CRUD/webhook, yoki BFF (Backend-for-Frontend — frontend'ga xizmat qiluvchi yupqa API qatlami), jamoa Next.js bilan tanish. Alohida backend kerak (NestJS — 08-QISM) — murakkab domen (ko'p modul, dependency injection, guards, interceptors), bir nechta mijoz bitta API'dan foydalansa (web + mobil + admin panel + uchinchi tomon — API mustaqil bo'lishi kerak), og'ir fon vazifalar (message queue, cron, uzoq ishlar — Next serverless funksiyalar vaqt cheklovi bor), mikroservis arxitekturasi, yoki backend jamoasi alohida ishlaydi. Ikki nuqta: (1) rate limit — 429 status (Upstash edge Redis; IP bo'yicha sirpanuvchi oyna); (2) Next API — kichik-o'rta/BFF/oddiy (bitta deploy qulay), alohida NestJS — murakkab domen/ko'p mijoz/og'ir fon (08-QISM). Amaliy naqsh: ko'p loyiha Next Route Handlers'dan boshlaydi (tez, bitta deploy), keyin murakkablashganda backend'ni NestJS'ga ajratadi (Next faqat frontend + BFF qoladi). To'g'ri qaror — loyiha hajmi va jamoaga bog'liq (over-engineering'dan qoching — kichik loyihaga mikroservis shart emas).


3. Sintaksis — tez ma'lumotnoma

text
ROUTE HANDLER 2.1-bob:  app/api/x/route.ts  export async function GET/POST(req) {...}
JAVOB 2.3-bob:          Response.json(data, { status: 201 })
BODY 2.4-bob:           const body = await request.json()
QUERY 2.4-bob:          new URL(request.url).searchParams.get("page")
HEADER 2.4-bob:         request.headers.get("authorization")
DINAMIK 2.5-bob:        GET(req, { params })  const { id } = await params
MIDDLEWARE 2.7-bob:     middleware.ts  middleware(request)  NextResponse.next()/redirect()
MATCHER 2.8-bob:        export const config = { matcher: ["/dashboard/:path*"] }
RUNTIME 2.9-bob:        export const runtime = "edge" | "nodejs"
CORS 2.10-bob:          headers: { "Access-Control-Allow-Origin": "*" }
OPTIONS 2.11-bob:       export async function OPTIONS() {...}  // CORS preflight
DINAMIK 2.11-bob:       export const dynamic = "force-dynamic"  // GET keshlanmasin
RATE LIMIT 2.12-bob:    ratelimit.limit(ip)  success ? next : 429

4. Batafsil kod namunalari

Har misol: Maqsad + izohli kod + "Bu kod nima qiladi".

Misol 1 — Asosiy REST API (GET + POST — 2.1, 2.2)

Maqsad: Mahsulotlar uchun asosiy REST API endpoint yaratish — ro'yxat (GET) va yaratish (POST). Bu Route Handler'ning eng asosiy ishlatilishi.

tsx
// app/api/products/route.ts  /api/products
import { db } from "@/lib/db";

// GET /api/products — ro'yxat (sahifalash bilan):
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const page = Number(searchParams.get("page") ?? "1");   // ?page=2
  const limit = 10;

  const products = await db.product.findMany({
    skip: (page - 1) * limit,    // sahifalash (offset)
    take: limit,
  });
  return Response.json({ products, page });   // JSON javob
}

// POST /api/products — yangi yaratish:
export async function POST(request: Request) {
  const body = await request.json();          // so'rov tanasi
  const product = await db.product.create({ data: body });
  return Response.json(product, { status: 201 });   // 201 Created
}

Bu kod nima qiladi: Bu — asosiy REST API endpoint (collection darajasida — /api/products). GET — mahsulotlar ro'yxatini qaytaradi: new URL(request.url).searchParams.get("page") (query param — ?page=2 — sahifalash uchun — 2.4), keyin DB'dan skip/take bilan (sahifalash — offset usuli — masalan 2-sahifa = 10-20-mahsulotlar — 6-QISM), va Response.json({ products, page }) (JSON javob — Web standart — 2.3). POST — yangi mahsulot yaratadi: await request.json() (so'rov tanasidan ma'lumot — yuborilgan mahsulot — 2.4), db.product.create (DB'ga yozish), Response.json(product, { status: 201 }) (201 Created — REST semantikasi — yangi resurs yaratildi — 2.2). Endi bu endpoint universal: uni mobil ilova (fetch("https://saytim.com/api/products")), boshqa sayt, Postman, yoki o'z Next.js client'ingiz — har kim ishlata oladi (HTTP/JSON — universal til). Server Action 13.5-bob bunday emas (faqat o'z komponentlaringiz) — Route Handler esa ochiq REST API 2.6-bob. Eslatma: production'da POST'da validatsiya (Zod — 13.5: 2.9) va autentifikatsiya (2.11 kabi) qo'shilishi shart (bu yerda soddalik uchun qisqartildi) — chunki har kim POST qila oladi. Bu — REST API'ning asosiy "g'isht"i (collection — ro'yxat va yaratish).

Misol 2 — Dinamik REST API ([id] — to'liq CRUD — 2.5)

Maqsad: Bitta mahsulot uchun to'liq CRUD endpoint — olish (GET), yangilash (PUT), o'chirish (DELETE) — [id] bilan. Bu REST resurs naqshining item darajasi.

tsx
// app/api/products/[id]/route.ts  /api/products/42
import { db } from "@/lib/db";

type Ctx = { params: Promise<{ id: string }> };   // dinamik params tipi

// GET /api/products/42 — bitta:
export async function GET(request: Request, { params }: Ctx) {
  const { id } = await params;
  const product = await db.product.findUnique({ where: { id } });
  if (!product) return Response.json({ error: "Topilmadi" }, { status: 404 });  // 404
  return Response.json(product);
}

// PUT /api/products/42 — yangilash:
export async function PUT(request: Request, { params }: Ctx) {
  const { id } = await params;
  const body = await request.json();
  const updated = await db.product.update({ where: { id }, data: body });
  return Response.json(updated);
}

// DELETE /api/products/42 — o'chirish:
export async function DELETE(request: Request, { params }: Ctx) {
  const { id } = await params;
  await db.product.delete({ where: { id } });
  return new Response(null, { status: 204 });   // 204 No Content (javob tanasi yo'q)
}

Bu kod nima qiladi: Bu — REST resurs naqshining item darajasi (/api/products/[id] — bitta mahsulot — 2.5). Uch HTTP metod, bir faylda ([id]/route.ts): (1) GET /api/products/42 — bitta mahsulotni oladi: await params (URL'dagi id — 2.5), db.product.findUnique, topilmaganda 404 (Response.json({ error }, { status: 404 }) — REST semantika — mijoz "yo'q" ekanini biladi — 2.2); (2) PUT /api/products/42 — yangilaydi: request.json() (yangi ma'lumot), db.product.update; (3) DELETE /api/products/42 — o'chiradi: db.product.delete, new Response(null, { status: 204 }) (204 No Content — o'chirildi, javob tanasi yo'q — 2.2). Ctx tipi ({ params: Promise<{ id: string }> }) — dinamik params'ning TypeScript tipi (qayta ishlatsa bo'ladi — 11.14). Misol 1 (collection — /products — ro'yxat, yaratish) + bu Misol (item — /products/[id] — olish, yangilash, o'chirish) = to'liq REST API (CRUD — 7-QISM): GET /products (ro'yxat), POST /products (yaratish), GET /products/42 (bitta), PUT /products/42 (yangilash), DELETE /products/42 (o'chirish). Bu — standart RESTful API strukturasi (har resurs uchun — mahsulot, foydalanuvchi, post). Express/NestJS'da (7, 8-QISM) shuncha route + controller kerak edi — Next.js'da fayl strukturasi (collection va item — ikki papka). Bu — mobil ilova, tashqi mijoz, yoki SPA frontend uchun to'liq backend API.

Misol 3 — Webhook (tashqi xizmat — 2.1, 2.10)

Maqsad: Tashqi xizmatdan (masalan to'lov tizimi) webhook qabul qilish — imzo tekshiruvi bilan. Bu Route Handler'ning Server Action qila olmaydigan muhim ishi.

tsx
// app/api/webhooks/stripe/route.ts  /api/webhooks/stripe
import { db } from "@/lib/db";

export async function POST(request: Request) {
  const body = await request.text();                  //  webhook xom matn (JSON emas — imzo uchun)
  const signature = request.headers.get("stripe-signature");  // imzo header'i

  // 1. IMZO TEKSHIR — webhook haqiqatan Stripe'dan keldimi? (soxta'dan himoya — 2.10):
  let event;
  try {
    event = verifyStripeSignature(body, signature, process.env.STRIPE_WEBHOOK_SECRET);
  } catch {
    return Response.json({ error: "Noto'g'ri imzo" }, { status: 400 });   // soxta webhook — rad
  }

  // 2. HODISANI QAYTA ISHLA (to'lov muvaffaqiyatli bo'lsa):
  if (event.type === "payment_intent.succeeded") {
    await db.order.update({
      where: { id: event.data.object.metadata.orderId },
      data: { status: "paid" },                       // buyurtma to'landi
    });
  }

  return Response.json({ received: true });            // Stripe'ga "qabul qilindi" (200)
}

Bu kod nima qiladi: Bu — webhook qabul qilish (Route Handler'ning Server Action qila olmaydigan muhim ishi — tashqi xizmat bilan muloqot). Webhook — tashqi xizmat (Stripe to'lov tizimi) sizning serveringizga avtomatik so'rov yuborishi (masalan to'lov muvaffaqiyatli bo'lganda Stripe sizga "to'landi" deb xabar beradi). Bu uchun URL'li endpoint kerak (/api/webhooks/stripe) — Stripe shu URL'ga POST yuboradi. Oqim: (1) request.text() (webhook tanasini xom matn sifatida olamiz — JSON emas, chunki imzo tekshiruvi xom matn talab qiladi); (2) stripe-signature header'ini olamiz; (3) imzo tekshirverifyStripeSignature(...) (webhook haqiqatan Stripe'dan kelganini tasdiqlaydi — STRIPE_WEBHOOK_SECRET bilan — 2.10) — bu majburiy (aks holda har kim soxta webhook yuborib, "to'landi" deyishi mumkin — firibgarlik; imzo tekshiruvi buni oldini oladi); imzo noto'g'ri bo'lsa 400 (rad); (4) hodisani qayta ishla — agar payment_intent.succeeded (to'lov muvaffaqiyatli), buyurtma holatini "paid" qiladi (DB'da); (5) Stripe'ga 200 (qabul qilindi — aks holda Stripe qayta urinadi). Nega Server Action emas: Stripe (tashqi xizmat) sizning Server Action'ingizni chaqira olmaydi (u faqat o'z komponentlaringiz uchun — 2.6) — webhook uchun standart HTTP endpoint (Route Handler) kerak. Bu — Route Handler'ning asosiy holatlaridan biri (to'lov, GitHub, tashqi integratsiya). Imzo tekshiruvi — webhook xavfsizligining asosi (soxta webhook'dan himoya — 14-QISM).

Misol 4 — Auth middleware (himoyalangan yo'l — 2.7)

Maqsad: Himoyalangan yo'llarni (/dashboard) markaziy himoyalash — middleware bilan token tekshir, yo'qsa login'ga. Bu har sahifada guard yozishdan qutqaradi.

tsx
// middleware.ts (loyiha ildizida)
import { NextRequest, NextResponse } from "next/server";

export function middleware(request: NextRequest) {
  const token = request.cookies.get("token")?.value;   // sessiya cookie
  const { pathname } = request.nextUrl;

  // 1. Himoyalangan yo'l + token yo'q  login'ga:
  if (pathname.startsWith("/dashboard") && !token) {
    const loginUrl = new URL("/login", request.url);
    loginUrl.searchParams.set("from", pathname);        // qaytib kelish uchun (login'dan keyin)
    return NextResponse.redirect(loginUrl);             // yo'naltir
  }

  // 2. Login sahifa + token BOR  dashboard'ga (kirgan odam login ko'rmasin):
  if (pathname === "/login" && token) {
    return NextResponse.redirect(new URL("/dashboard", request.url));
  }

  return NextResponse.next();   // boshqa hollarda — davom ettir (sahifaga o'tsin)
}

// Faqat shu yo'llapga ishlasin (matcher — 2.8):
export const config = {
  matcher: ["/dashboard/:path*", "/login"],
};

Bu kod nima qiladi: Bu — markaziy auth guard (har so'rov sahifaga yetishdan oldin — 2.7). middleware.ts har so'rovni "ushlaydi": request.cookies.get("token") (sessiya cookie — kirgan'mi), request.nextUrl.pathname (joriy yo'l). Ikki qoida: (1) himoyalangan yo'l + token yo'q — agar /dashboardga kirmoqchi bo'lsa, lekin token yo'q (kirmagan), NextResponse.redirectbilan login'ga yo'naltiradi (from query bilan — login'dan keyin shu sahifaga qaytab kelish uchun — UX); (2) login + token bor — agar allaqachon kirgan odam /loginga borsa, uni dashboard'ga yo'naltiradi (kirgan odam login formani ko'rishi keraksiz). Boshqa hollarda NextResponse.next() (davom — sahifaga o'tsin). matcher (["/dashboard/:path*", "/login"]) — middleware faqat shu yo'llarga ishlaydi (boshqa sahifalar — bosh, about — middleware'dan o'tmaydi — performance — 2.8). Nega middleware (har sahifada guard o'rniga — 13.2: Misol 8): (1) markaziy — bir joyda butun himoya (har /dashboard/* sahifaga alohida guard yozish shart emas); (2) tezroq — middleware edge'da (foydalanuvchiga yaqin — 2.9), sahifa render bo'lishidan oldin to'xtatadi (himoyalangan kontent server'da ham render bo'lmaydi — 13.2: Misol 8'dan ham erta). Bu — Next.js'da autentifikatsiya guard'ning eng toza, markaziy usuli (13.9 — NextAuth — bilan birlashadi). Middleware — global auth nazoratining ideal joyi.

Misol 5 — i18n middleware (til yo'naltirish — 2.8)

Maqsad: Foydalanuvchini tiliga qarab to'g'ri til versiyasiga yo'naltirish (/uz, /en) — middleware bilan. Bu ko'p tilli sayt uchun asosiy.

tsx
// middleware.ts
import { NextRequest, NextResponse } from "next/server";

const locales = ["uz", "en", "ru"];
const defaultLocale = "uz";

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // Yo'lda til prefiksi bormi? (/uz/..., /en/...):
  const hasLocale = locales.some(
    (loc) => pathname.startsWith(`/${loc}/`) || pathname === `/${loc}`
  );
  if (hasLocale) return NextResponse.next();   // til bor — davom

  // Til yo'q  foydalanuvchi tilini aniqla (Accept-Language header'dan):
  const acceptLang = request.headers.get("accept-language") ?? "";
  const detected = locales.find((loc) => acceptLang.includes(loc)) ?? defaultLocale;

  // To'g'ri til bilan yo'naltir (/about  /uz/about):
  return NextResponse.redirect(new URL(`/${detected}${pathname}`, request.url));
}

export const config = {
  matcher: ["/((?!_next|api|favicon.ico).*)"],   // statik/api bundan tashqari
};

Bu kod nima qiladi: Bu — i18n (xalqarolashtirish) middleware — foydalanuvchini tiliga qarab yo'naltirish 2.8-bob. Ko'p tilli saytda URL'da til prefiksi bo'ladi (/uz/about, /en/about — har til alohida). Middleware: (1) til prefiksi bormi tekshirlocales.some(...) (/uz/, /en/ bilan boshlanadimi); agar bor — next() (davom — til allaqachon to'g'ri); (2) til yo'q bo'lsa aniqlarequest.headers.get("accept-language") (brauzer yuboradigan til afzalligi — masalan "uz-UZ,en;q=0.9"), undan mos tilni topadi (detected), topilmasa defaultLocale (uz); (3) to'g'ri til bilan yo'naltir/about /uz/about (NextResponse.redirect — foydalanuvchi o'z tilidagi versiyaga o'tadi). matcher — statik fayllar (_next), API (api), favicon bundan tashqari (ularga til prefiksi keraksiz — faqat sahifalarga). Demak: foydalanuvchi /aboutga kirsa, middleware uni brauzer tiliga qarab /uz/about (yoki /en/about)ga yo'naltiradi (avtomatik — to'g'ri til). Bu ko'p tilli sayt (e-commerce, hujjat, blog — turli mamlakat foydalanuvchilari) uchun asosiy (har foydalanuvchi o'z tilida ko'radi). Middleware bu yerda ideal — har so'rov til tekshiruvidan o'tadi (markaziy — har sahifada til logikasini yozish o'rniga). Real loyihada next-intl kabi kutubxona bu logikani soddalashtiradi (lekin asosi — shu middleware naqshi). i18n — middleware'ning klassik qo'llanishi.

Misol 6 — Query bilan filtr/saralash API (2.4)

Maqsad: Query parametrlar bilan moslashuvchan API — filtr, saralash, sahifalash. Bu real-dunyo API'ning standart imkoniyati.

tsx
// app/api/products/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);

  // Query parametrlarni o'qi (hammasi ixtiyoriy — default bilan):
  const category = searchParams.get("category");         // ?category=phone
  const minPrice = Number(searchParams.get("minPrice") ?? "0");  // ?minPrice=100
  const sort = searchParams.get("sort") ?? "createdAt";  // ?sort=price
  const page = Number(searchParams.get("page") ?? "1");

  // Query'dan DB so'rovini DINAMIK qur:
  const products = await db.product.findMany({
    where: {
      ...(category && { category }),         // category berilgan bo'lsa filtr
      price: { gte: minPrice },              // minPrice'dan katta
    },
    orderBy: { [sort]: "desc" },             // saralash (dinamik maydon)
    skip: (page - 1) * 20,
    take: 20,
  });

  return Response.json({ products, page });
}
//  /api/products?category=phone&minPrice=500&sort=price&page=2

Bu kod nima qiladi: Bu — query parametrlar bilan moslashuvchan API (filtr, saralash, sahifalash — 2.4). Real API'lar bir necha ixtiyoriy parametrni qabul qiladi: /api/products?category=phone&minPrice=500&sort=price&page=2. Handler har birini searchParams.get(...) bilan o'qiydi (default qiymat bilan — ?? "0", ?? "1" — berilmasa standart): category (filtr — qaysi turkum), minPrice (narx chegarasi), sort (saralash maydoni), page (sahifa). Keyin bu parametrlardan dinamik DB so'rovi quriladi: where ichida ...(category && { category }) (faqat category berilgan bo'lsa filtr qo'shadi — yo'q bo'lsa hammasi), price: { gte: minPrice } (narx minPricedan katta), orderBy: { [sort]: "desc" } (dinamik maydon bo'yicha saralash — [sort] — kompyuted property — 11.2), skip/take (sahifalash). Natija: bitta endpoint ko'p so'rovga javob beradi — barcha mahsulot, faqat telefonlar, faqat qimmatlari, narx bo'yicha saralangan, 2-sahifa — query parametrlar orqali (mijoz qaysi parametrni yuborsa, shunga mos javob). Bu — real-dunyo API'ning standart imkoniyati (filtr, saralash, sahifalash — har e-commerce, ro'yxat API'sida). Mijoz (mobil ilova, frontend) query orqali kerakli ma'lumotni so'raydi. Eslatma: production'da query qiymatlarini validatsiya qilish kerak (Zod — minPrice raqammi, sort ruxsat etilgan maydonmi — SQL injection/xato'dan himoya — 14-QISM). Bu — moslashuvchan REST API'ning asosi.

Misol 7 — Xavfsizlik header'lari middleware (2.8, 2.10)

Maqsad: Barcha javobga xavfsizlik header'lari qo'shish — middleware bilan markaziy. Bu butun saytni bir joydan himoyalaydi (14-QISM ko'prik).

tsx
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const response = NextResponse.next();   // so'rovni davom ettir, lekin javobni ushla

  //  Har javobga xavfsizlik header'lari qo'sh (butun sayt — markaziy — 14-QISM):
  response.headers.set("X-Frame-Options", "DENY");                  // clickjacking'dan
  response.headers.set("X-Content-Type-Options", "nosniff");        // MIME sniffing'dan
  response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
  response.headers.set(
    "Content-Security-Policy",
    "default-src 'self'; script-src 'self'"                         // XSS'dan (CSP — 14-QISM)
  );

  return response;   // header'lar bilan javob
}

export const config = { matcher: "/:path*" };   // barcha yo'l

Bu kod nima qiladi: Bu — xavfsizlik header'larini markaziy qo'shish (middleware bilan — 2.8, 2.10, 14-QISM ko'prik). NextResponse.next() — so'rovni davom ettiradi, lekin javob obyektini qaytaradi (uni o'zgartirishimiz mumkin). Keyin javobga xavfsizlik header'lari qo'shamiz (har biri ma'lum hujumdan himoya — 14-QISM): (1) X-Frame-Options: DENY — sahifani <iframe>da ko'rsatishni taqiqlaydi (clickjacking hujumidan — yomon sayt sizning sahifangizni yashirin iframe'da ko'rsatib, foydalanuvchini aldashi); (2) X-Content-Type-Options: nosniff — brauzer MIME turini "taxminlash"ini taqiqlaydi (MIME sniffing hujumidan); (3) Referrer-Policy — referrer ma'lumotini cheklaydi (maxfiylik); (4) Content-Security-Policy (CSP) — qaysi manbalardan script/stil yuklanishini cheklaydi (XSS hujumidan — eng muhim — faqat 'self' — o'z domeningiz — 14-QISM). matcher: "/:path*"barcha yo'l (butun sayt himoyalangan). Nega middleware (har sahifada header qo'shish o'rniga): markaziy — bir joyda butun sayt himoyalandi (har sahifa, har Route Handler javobiga avtomatik header — birortasi unutilmaydi). Bu — xavfsizlik header'larining (web ilova himoyasining asosiy qatlami) ideal joyi (markaziy, butun sayt). 14-QISM (Xavfsizlik)da bu header'lar va hujumlar chuqur ochiladi — bu yerda middleware'ning xavfsizlik roli ko'rsatildi (markaziy himoya nuqtasi). Middleware faqat auth/redirect emas, balki butun saytni himoyalashning ham vositasi.

Misol 8 — Streaming response (2.3)

Maqsad: Katta yoki sekin ma'lumotni oqimli (streaming) javob bilan yuborish — Route Handler'da. Bu AI javob, katta fayl, real-time uchun.

tsx
// app/api/stream/route.ts — oqimli javob (ma'lumot bo'laklab keladi)
export async function GET() {
  // ReadableStream — ma'lumotni BO'LAKLAB yuborish (butunni kutmasdan):
  const stream = new ReadableStream({
    async start(controller) {
      const encoder = new TextEncoder();
      for (let i = 1; i <= 5; i++) {
        controller.enqueue(encoder.encode(`Ma'lumot bo'lagi ${i}\n`));   // bo'lak yubor
        await new Promise((r) => setTimeout(r, 1000));   // 1s kutib (simulyatsiya)
      }
      controller.close();   // oqim tugadi
    },
  });

  return new Response(stream, {
    headers: { "Content-Type": "text/plain; charset=utf-8" },
  });
}

Bu kod nima qiladi: Bu — streaming response (oqimli javob — 2.3). Oddiy API javob butun ma'lumotni bir vaqtda yuboradi (mijoz hammasini kutadi). Streaming — ma'lumotni bo'laklab yuborish (mijoz har bo'lakni kelgani zahoti oladi — butunni kutmasdan). ReadableStream (Web standart) — oqim yaratadi: start(controller) ichida controller.enqueue(...) (har bo'lakni oqimga qo'shadi — TextEncoder bilan matnni baytga), await setTimeout (bu yerda 1 soniya kutish — sekin ma'lumot simulyatsiyasi), controller.close() (oqim tugadi). Javob new Response(stream, ...) — oqimni qaytaradi. Natijada: mijoz "Ma'lumot bo'lagi 1" ni darrov oladi (1 soniyadan keyin), keyin "2" (yana 1 soniya), va hokazo — butun 5 bo'lakni (5 soniya) kutmasdan, har bo'lakni kelgani zahoti ko'radi. Qachon kerak: (1) AI javob (ChatGPT kabi — javob harf-harf "yozilayotgandek" keladi — streaming — eng keng zamonaviy holati); (2) katta fayl (butunni xotipaga yuklamasdan oqimli); (3) real-time ma'lumot (jonli yangilanishlar). Bu — Web standart ReadableStreamning Route Handler'da ishlatilishi (13.4: 2.8 — sahifa streaming'idan farqli — bu API darajasida). AI ilovalar uchun ayniqsa muhim (LLM javobini oqimli ko'rsatish — foydalanuvchi kutmaydi, javob "yoziladi"). Streaming — zamonaviy API'ning (ayniqsa AI) muhim imkoniyati.

Misol 9 — Route Handler vs Server Action qarori (2.6)

Maqsad: Bir vazifani ikki usulda (Route Handler va Server Action) ko'rsatib, qachon qaysi to'g'ri ekanini amaliy ko'rsatish. Bu eng keng chalkashlikni hal qiladi.

tsx
// HOLAT: blog post yaratish

//  KERAKSIZ MURAKKAB — o'z forma uchun Route Handler (API + client fetch):
// app/api/posts/route.ts
export async function POST(req: Request) {
  const body = await req.json();
  return Response.json(await db.post.create({ data: body }));
}
// + Client'da: fetch("/api/posts", { method: "POST", body: JSON.stringify(...) })
//  2 fayl, JSON serializatsiya, xato boshqaruvi qo'lda (KERAKSIZ — o'z forma uchun)

//  SODDA — o'z forma uchun Server Action 13.5-bob:
// app/posts/actions.ts
"use server";
export async function createPost(formData: FormData) {
  await db.post.create({ data: { title: formData.get("title") } });
  revalidatePath("/posts");
}
// + <form action={createPost}> (bitta funksiya — API yo'q)

//  TO'G'RI Route Handler — MOBIL ilova post yaratca (tashqi mijoz):
// app/api/posts/route.ts  mobil app fetch qiladi (Server Action ishlamaydi — 2.6)

Bu kod nima qiladi: Bu — eng keng chalkashlikni hal qiladi (Route Handler vs Server Action — 2.6). Holat: blog post yaratish. Noto'g'ri yo'l (o'z forma uchun Route Handler): app/api/posts/route.ts (POST handler) + client'da fetch("/api/posts", { method: "POST", ... }) — bu ikki fayl, JSON serializatsiya (qo'lda JSON.stringify/.json()), xato boshqaruvi qo'lda — keraksiz murakkab o'z formangiz uchun. To'g'ri yo'l (o'z forma uchun Server Action): app/posts/actions.ts ("use server" + createPost) + <form action={createPost}>bitta funksiya, API yo'q, fetch yo'q, type-safe 13.5-bob — ancha sodda. Lekin — agar mobil ilova (React Native) post yaratsa, u sizning Server Action'ingizni chaqira olmaydi (Server Action faqat o'z Next.js komponentlaringiz uchun — 2.6), shuning uchun mobil uchun Route Handler (/api/posts) kerak (mobil fetch qiladi — universal HTTP). Demak qaror: (1) o'z Next.js forma/komponentlar Server Action (soddaroq); (2) tashqi mijoz (mobil, webhook, boshqa sayt) Route Handler (REST — universal). Keng xato — o'z formangiz uchun Route Handler yozib (eski SPA odati — API + fetch), Server Action'ning soddaligini o'tkazib yuborish. Ba'zan ikkalasi kerak (web forma — Server Action, mobil — Route Handler — bir mantiqni ikki interfeys orqali). To'g'ri tanlov — keraksiz kodni kamaytiradi (ichki Action, tashqi Handler). Bu — Next.js backend arxitekturasini to'g'ri qurishning kaliti.

Misol 10 — To'liq himoyalangan API (auth + validatsiya — 2.4, 2.10)

Maqsad: Production-darajadagi himoyalangan Route Handler — autentifikatsiya + validatsiya + xato boshqaruvi. Bu real API endpoint'ning to'liq strukturasi.

tsx
// app/api/posts/route.ts
import { z } from "zod";
import { getServerSession } from "@/lib/auth";

const CreatePostSchema = z.object({
  title: z.string().min(3),
  content: z.string().min(10),
});

export async function POST(request: Request) {
  // 1. AUTENTIFIKATSIYA (kim? — token/sessiya):
  const session = await getServerSession();
  if (!session) {
    return Response.json({ error: "Avtorizatsiya kerak" }, { status: 401 });  // 401
  }

  // 2. VALIDATSIYA (Zod — kirish ma'lumotini tekshir):
  const body = await request.json();
  const result = CreatePostSchema.safeParse(body);
  if (!result.success) {
    return Response.json(
      { error: "Noto'g'ri ma'lumot", details: result.error.flatten() },
      { status: 400 }   // 400 Bad Request
    );
  }

  // 3. MUTATION (faqat valid + autentifikatsiyalgan — authorId session'dan):
  try {
    const post = await db.post.create({
      data: { ...result.data, authorId: session.user.id },
    });
    return Response.json(post, { status: 201 });   // 201 Created
  } catch {
    return Response.json({ error: "Server xatosi" }, { status: 500 });  // 500
  }
}

Bu kod nima qiladi: Bu — production-darajadagi, to'liq himoyalangan Route Handler (autentifikatsiya + validatsiya + xato boshqaruvi — real API'ning strukturasi — 13.5: Misol 8'ning Route Handler versiyasi). To'rt qatlam (har biri to'g'ri HTTP status bilan): (1) autentifikatsiyagetServerSession() (kim chaqiryapti? — token/sessiya); kirmagan bo'lsa 401 Unauthorized (REST semantika — "avtorizatsiya kerak"); (2) validatsiya — Zod (CreatePostSchema.safeParse — title/content to'g'rimi — 13.5: 2.9); noto'g'ri bo'lsa 400 Bad Request (xato tafsilotlari bilan — mijoz nimani tuzatishni biladi); (3) mutationtry/catch ichida DB'ga yozish (authorId: session.user.id — muallif autentifikatsiyalgan foydalanuvchi, so'rov tanasidan emas — xavfsiz — aks holda har kim boshqa nomidan post yarata olardi — 13.5: Misol 8), muvaffaqiyatli bo'lsa 201 Created; (4) xato boshqaruvicatch bilan server xatosini ushlash (500 Internal Server Error — DB ishlamasa). Har bosqich to'g'ri HTTP status (401 auth, 400 validatsiya, 201 yaratildi, 500 server) — REST semantikasi (mijoz har holatni to'g'ri tushunadi — 2.2). Bu — har production REST endpoint'ning strukturasi (autentifikatsiya validatsiya mutation status). Route Handler ochiq endpoint (har kim chaqira oladi — mobil, Postman, hatto yomon niyatli), shuning uchun bu himoyalar majburiy (server'da bo'lgani uni xavfsiz qilmaydi — 13.5: 2.11 kabi). Bu — Express/NestJS controller'ining (7, 8-QISM) Next.js, Web-standart versiyasi (to'liq himoyalangan API endpoint). Mobil ilova, tashqi mijoz uchun professional backend.

Misol 11 — CORS + OPTIONS preflight (public API — 2.10, 2.11)

Maqsad: Boshqa domendan (tashqi frontend, mobil web) murojaat qilinadigan public API — CORS header'lari va OPTIONS preflight bilan. Bu tashqi mijozga API'ni ochadi.

tsx
// app/api/public/products/route.ts  boshqa domendan chaqiriladigan API
import { db } from "@/lib/db";

//  CORS header'lari — bir joyda (qayta ishlatish uchun):
const corsHeaders = {
  "Access-Control-Allow-Origin": "https://mijoz-sayt.com",  // aniq domen (xavfsizroq)
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
};

// OPTIONS — preflight (brauzer asosiy so'rovdan OLDIN avtomatik yuboradi):
export async function OPTIONS() {
  return new Response(null, { status: 204, headers: corsHeaders });
}

// GET — ma'lumot (CORS header bilan — boshqa domen o'qiy oladi):
export async function GET() {
  const products = await db.product.findMany({ take: 20 });
  return Response.json(products, { headers: corsHeaders });   //  har javobda CORS
}

Bu kod nima qiladi: Bu — public API (boshqa domendan murojaat qilinadigan — CORS + OPTIONS — 2.10, 2.11). O'z Next.js sahifangizdan API'ni chaqirganda CORS kerak emas (bir domen). Lekin API'ni boshqa domen (tashqi frontend, mobil web-ilova, hamkor sayt) chaqirsa — brauzer same-origin policy (xavfsizlik qoidasi) tufayli javobni bloklaydi, agar server aniq CORS header'lari bilan ruxsat bermasa. Oqim: (1) corsHeaders — bir joyda (Access-Control-Allow-Origin — aniq domen "*" o'rniga xavfsizroq, chunki "*" har kimga ochadi; Allow-Methods, Allow-Headers); (2) OPTIONS handler — brauzer murakkab so'rovdan (masalan Authorization header bilan) oldin avtomatik OPTIONS "preflight" yuboradi ("ruxsat bormi?") — server 204 + CORS header qaytaradi (ruxsat berildi), keyin brauzer asosiy so'rovni yuboradi 2.11-bob; (3) GET — javobga corsHeaders qo'shadi (boshqa domen o'qiy oladi). OPTIONS bo'lmasa, PUT/DELETE yoki maxsus header bilan CORS so'rov ishlamaydi (preflight muvaffaqiyatsiz). Bu — public API yoki mikro-frontend arxitekturasi uchun asosiy (tashqi domenga API ochish). Xavfsizlik: Allow-Origin'ni "*" emas, aniq ishonchli domen(lar)ga cheklang (aks holda har kim API'ngizni ishlatadi — 14-QISM).

Misol 12 — Rate limiting (so'rov cheklash — 2.12)

Maqsad: API'ni haddan tashqari so'rovdan (DDoS, brute-force, abuse) himoyalash — IP bo'yicha rate limiting. Bu login yoki public API uchun zarur himoya qatlami.

tsx
// app/api/login/route.ts — rate limit bilan himoyalangan login
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

// Har IP uchun: 10 soniyada 5 urinish (brute-force'dan himoya):
const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(5, "10 s"),
});

export async function POST(request: Request) {
  // 1. IP'ni aniqla (proxy orqali kelsa x-forwarded-for):
  const ip = request.headers.get("x-forwarded-for")?.split(",")[0] ?? "anon";

  // 2. RATE LIMIT tekshir:
  const { success, remaining } = await ratelimit.limit(ip);
  if (!success) {
    return Response.json(
      { error: "Juda ko'p urinish. Birozdan keyin qayta urining." },
      { status: 429, headers: { "Retry-After": "10" } },   // 429 Too Many Requests
    );
  }

  // 3. Limit ichida — normal login logikasi:
  const { email, password } = await request.json();
  // ... autentifikatsiya 13.9-bob ...
  return Response.json({ ok: true, remaining });
}

Bu kod nima qiladi: Bu — rate limiting (so'rov cheklash — 2.12). Login endpoint ochiq (har kim POST qila oladi), shuning uchun brute-force hujum xavfi bor (bot minglab parol urinib ko'rishi mumkin). Rate limiting buni to'xtatadi: har IP uchun qisqa vaqtda cheklangan so'rov. Oqim: (1) IP aniqlashx-forwarded-for header (foydalanuvchi proxy/CDN orqali kelsa, haqiqiy IP shu yerda — birinchi qiymat); (2) ratelimit.limit(ip) — Upstash Redis'da (edge'ga mos serverless Redis — holat tashqarida, tarqoq serverlar uchun) IP hisoblagichini tekshiradi (slidingWindow(5, "10 s") — 10 soniyada 5 urinish); chegaradan oshsa success: false 429 Too Many Requests (Retry-After: 10 header — mijozga "10 soniyadan keyin urin" deb aytadi); (3) limit ichida bo'lsa — normal login davom etadi. Nega Upstash Redis (oddiy o'zgaruvchi emas): edge/serverless muhitda serverlar tarqoq (har so'rov boshqa serverga tushishi mumkin — xotira ulashilmaydi), shuning uchun hisoblagich markaziy joyda (Redis) bo'lishi kerak. Bu — public API, login, forma yuborish uchun zarur himoya (DDoS, abuse, brute-force'dan — 14-QISM). Middleware'da qo'llansa — butun API'ga bir joydan rate limit (yanada markaziy — 2.8).


5. To'g'ri va noto'g'ri holatlar

1) O'z forma uchun

text
 Route Handler + client fetch (keraksiz murakkab — 2.6)
 Server Action (soddaroq — Misol 9)

2) Tashqi mijoz uchun

text
 Server Action (mobil/webhook chaqira olmaydi — 2.6)
 Route Handler (REST — universal — Misol 3)

3) Status kodlar

text
 hamma narsaga 200 (xato ham 200 — REST buziladi)
 201/400/401/404/500 (to'g'ri status — REST semantika — 2.2)

4) Middleware og'irligi

text
 middleware'da DB so'rov (edge — sekin, cheklangan — 2.9)
 middleware yengil (auth/redirect); DB — Route Handler nodejs

5) matcher

text
 matcher yo'q (middleware har so'rovga — statik ham — sekin)
 matcher (faqat kerakli yo'l — 2.8)

6) Webhook xavfsizligi

text
 webhook imzosini tekshirmaslik (soxta webhook — firibgarlik)
 imzo tekshir (Stripe signature — 2.10, Misol 3)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Route Handler 405 Method Not Allowed

Sababi: so'ralgan metod (masalan PUT) export qilinmagan 2.2-bob. Yechimi: kerakli metod funksiyasini export qil (export async function PUT).

Xato 2 — params undefined (Route Handler)

Sababi: 2-argument { params } olinmagan yoki await yo'q 2.5-bob. Yechimi: (req, { params }) + await params (Misol 2).

Xato 3 — Middleware ishlamaydi

Sababi: middleware.ts noto'g'ri joyda (app ichida emas, ildizda bo'lishi kerak) yoki matcher noto'g'ri 2.7-bob. Yechimi: loyiha ildizida middleware.ts; matcher tekshir.

Xato 4 — Edge'da Prisma/DB ishlamaydi

Sababi: middleware/edge runtime'da DB drayveri 2.9-bob. Yechimi: DB'ni Route Handler nodejs'da; middleware faqat yengil (token tekshir).

Xato 5 — CORS xatosi (boshqa domendan)

Sababi: Access-Control header'lari yo'q 2.10-bob. Yechimi: Route Handler javobiga CORS header (Misol 2.10) + OPTIONS.

Xato 6 — Middleware infinite redirect loop

Sababi: redirect maqsad yo'li ham middleware'dan o'tib, yana redirect 2.7-bob. Yechimi: matcher'dan redirect maqsadini chiqar yoki shart qo'sh (login'da token bormi).

Xato 7 — Server Action'ni tashqi mijoz chaqira olmaydi

Sababi: Server Action faqat o'z komponentlar uchun 2.6-bob. Yechimi: tashqi mijoz uchun Route Handler (Misol 9).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Server Actions 13.5-bob: Route Handler — tashqi mijoz; Server Action — o'z forma 2.6-bob.
  • Auth 13.9-bob: middleware — auth guard; Route Handler — auth API.
  • REST/Express (7-QISM): Route Handler — REST API (Next.js versiyasi).
  • NestJS (08-QISM): Next API yetarli (kichik-o'rta/BFF) yoki alohida backend (murakkab/ko'p mijoz — 2.12).
  • Xavfsizlik (14): middleware — xavfsizlik header; webhook imzo; CORS.
  • Rendering 13.4-bob: Route Handler caching (revalidate/dynamic).
  • Deploy 13.11-bob: edge runtime — Vercel edge network (global, tez).
  • Mobil/tashqi: Route Handler — mobil app, webhook, public API.
  • i18n: middleware — til yo'naltirish.

8. Eng yaxshi amaliyotlar (best practices)

  • Route Handler tashqiga; Server Action ichkiga (2.6, Misol 9).
  • To'g'ri status kodlar (201/400/401/404/500 — REST — 2.2).
  • Validatsiya (Zod) + auth har endpoint'da (ochiq — Misol 10).
  • authorId session'dan (so'rov tanasidan emas — xavfsiz — Misol 10).
  • Middleware yengil (auth/redirect — edge; DB emas — 2.9).
  • matcher bilan nishonla (keraksiz so'rovga ishlamasin — 2.8).
  • Webhook imzo tekshir (soxta'dan — 2.10, Misol 3).
  • Xavfsizlik header middleware'da (CSP/X-Frame — markaziy — Misol 7).
  • CORS faqat kerakli domen ("*" emas — public API'da ehtiyot — 2.10).
  • DB nodejs runtime (edge cheklangan — 2.9).
  • OPTIONS handler public API'da (CORS preflight — 2.11, Misol 11).
  • Rate limit ochiq endpoint'da (login/public — 429 — 2.12, Misol 12).
  • Kichik-o'rta Next API; murakkab/ko'p mijoz alohida NestJS (08-QISM — 2.12).

9. Amaliy loyiha: "Next.js Backend (API + Middleware)"

Route Handlers va Middleware bilan to'liq backend qatlami — mustahkamlash.

Maqsad

Blog backend: REST API (mobil uchun), auth middleware, xavfsizlik header, webhook.

Talablar (requirements)

  1. REST API: posts CRUD (collection + [id] — Misol 1, 2).
  2. Status kodlar: 201/400/401/404/500 to'g'ri 2.2-bob.
  3. Auth API: himoyalangan endpoint (session — Misol 10).
  4. Validatsiya: Zod har POST/PUT'da (Misol 10).
  5. Auth middleware: /dashboard himoya (Misol 4).
  6. i18n yoki xavfsizlik header: middleware (Misol 5 yoki 7).
  7. matcher: to'g'ri nishonlash 2.8-bob.
  8. Webhook: imzo tekshir (Misol 3).
  9. Query API: filtr/saralash/sahifalash (Misol 6).
  10. Qaror: qaysi Route Handler, qaysi Server Action — izohla 2.6-bob.

Maslahatlar (hint)

  • O'z forma Server Action; tashqi Route Handler (Misol 9).
  • Status kodlar to'g'ri (Xato — REST).
  • Auth + validatsiya har endpoint (Misol 10).
  • Middleware yengil (DB emas — Xato 4).
  • matcher (Xato — har so'rovga emas).
  • Webhook imzo (Xato 6 — loop'dan ehtiyot).

"Tayyor" mezonlari (acceptance criteria)

  • REST API (CRUD — collection + item).
  • To'g'ri status kodlar.
  • Auth + validatsiya (himoyalangan endpoint).
  • Auth middleware (guard).
  • Xavfsizlik header yoki i18n (middleware).
  • matcher (nishonlangan).
  • Webhook (imzo).
  • Route Handler/Server Action qarori oqlangan.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda Next.js backend qatlamini — Route Handlers va Middleware — chuqur o'rgandik:

  • Route Handlers (route.ts — REST — 2.1); HTTP metodlar 2.2-bob; Request/Response 2.3-bob; so'rov o'qish 2.4-bob; dinamik [id] 2.5-bob.
  • Route Handler vs Server Action 2.6-bob; Middleware (so'rov ushlash — 2.7); holatlar/matcher 2.8-bob; edge/node runtime 2.9-bob; CORS/caching 2.10-bob; OPTIONS/HEAD, dinamik vs statik 2.11-bob; rate limiting, Next API vs alohida NestJS backend 2.12-bob.

Endi siz Next.js'ning to'liq backend imkoniyatlarini bilasiz: REST API (Route Handlers — mobil, webhook, tashqi mijoz uchun) va markaziy so'rov nazorati (Middleware — auth, i18n, xavfsizlik). Server Actions (13.5, ichki) + Route Handlers (tashqi) + Middleware (global) — Next.js full-stack backend'ining to'liq tasviri.

Keyingi bob — 13.7-bob: Caching va Performance. Next.js'ning eng murakkab, lekin eng kuchli mavzularidan biri — caching qatlamlarini chuqur ochamiz: Request Memoization (13.5: 2.3), Data Cache (fetch kesh), Full Route Cache (statik sahifa), Router Cache (client-side), va ularni qanday boshqarish (revalidate, tags), hamda performance optimizatsiya (rasm — next/image, shrift — next/font, bundle, lazy loading). Bu — Next.js'ni tez va samarali qilishning kaliti.


Foydalanilgan rasmiy/ishonchli manbalar

  • Next.js rasmiy hujjati (nextjs.org/docs) — "Route Handlers", "Middleware", "Routing"
  • nextjs.org — NextRequest/NextResponse, middleware.ts, config.matcher, Edge Runtime
  • MDN Web Docs — Request/Response, ReadableStream, CORS, HTTP status kodlar
  • Web standartlari — Fetch API, Web Streams, CORS preflight (OPTIONS); HTTP status kodlar (RFC 9110)
  • Stripe webhook hujjati — imzo tekshirish (stripe-signature); Upstash Ratelimit — edge rate limiting (429)
  • Next.js — Route Handler caching (dynamic/revalidate), Edge vs Node.js runtime; NestJS (08-QISM) — alohida backend qarori

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
13.6-bob: Route Handlers va Middleware — Wisar