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
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 Handler —
route.tsfaylda 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/productsendpoint; ichidaexport async function GET() { ... return Response.json(products) }(GET so'rovga javob — JSON) vaexport async function POST(request) { const body = await request.json(); ... }(POST — yangi yaratish). Papka strukturasipage.tsxkabi (13.2 — fayl-asosli), lekinroute.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 standartResponseobyekti — 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) varoute.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)
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.tsdaGET(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'dagirouter.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 (201yaratishda,204o'chirishda,404topilmaganda — 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)
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-QISMfetchAPI'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.jsNextRequest/NextResponse(next/server'dan) — Web standartining kengaytmasi (qo'shimcha qulaylik):NextRequestdareq.cookies.get()(cookie qulay),req.nextUrl(URL qulay);NextResponsedaNextResponse.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 — standartRequest/Response, qulaylik kerak bo'lgandaNextRequest/NextResponse.
2.4. So'rovni o'qish (body, query, header, cookie)
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-bobdauseSearchParamsning 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) yokiNextRequest.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'dagireq.body/req.query/req.headers/req.paramsning Next.js, Web-standart versiyasi — 7-QISM).
2.5. Dinamik Route Handler ([id])
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 naqshiDinamik 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/42id = "42"— Next.js 15: async — 13.2: 2.2). Topilmaganda404qaytarish muhim (Response.json({ error }, { status: 404 })— REST semantikasi — mijoz "yo'q" ekanini biladi). Bu — to'liq REST resurs naqshi: collection (/api/products—route.ts:GETro'yxat,POSTyaratish) va item (/api/products/[id]—[id]/route.ts:GETbitta,PUTyangilash,DELETEo'chirish) — har biri o'z faylda (collection va item alohida papka). Ikki nuqta: (1)[id]dinamik segmentparams(2-argument —await params); topilmaganda404(REST semantika — to'g'ri status); (2) collection (/products) va item (/products/[id]) — REST resurs naqshi (standart struktura — har RESTful API shunday). Bu — Express'dagirouter.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)
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'ridanawait(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'ridanawait(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
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. Middleware —
middleware.tsfaylda (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). Ichidarequest.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), yokiNextResponse.next()(davom ettirish — sahifaga o'tsin), yokiNextResponse.rewrite(...)(yashirin — URL o'zgarmaydi, lekin boshqa kontent).config.matcher2.8-bob — middleware qaysi yo'llarga ishlashini belgilaydi. Oqim: so'rov middleware (tekshir/o'zgartir)next()(sahifaga) yokiredirect(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
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 yokiAccept-Languageheader'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
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'ningfs, to'liqcrypto, 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) yokiexport 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 Handlernodejs'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
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 imzoCORS, caching va best practices — Route Handlers/Middleware'ni professional ishlatish. CORS (Cross-Origin Resource Sharing — 7-QISM) — boshqa domendan (masalan
app.com'danapi.com'ga) so'rovga ruxsat: Route Handler javobigaAccess-Control-Allow-Originheader ("*"— har domen, yoki aniq domen — xavfsizroq) vaAccess-Control-Allow-Methodsqo'shish; ba'zanOPTIONSmetod (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,matcherbilan nishonlash — 2.8); (4) DB kerak Route Handlernodejs(edge emas — 2.9); (5) xavfsizlik header'lari middleware'da (CSP, X-Frame — 14-QISM); (6) webhook'da imzo tekshir (Stripesignature— webhook haqiqatan Stripe'dan kelganini tasdiqlash — soxta webhook'dan himoya — xavfsizlik). Ikki nuqta: (1) CORS — tashqi domen so'rovga ruxsat (Access-Controlheader'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
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 yangiOPTIONS, 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 (masalanAuthorizationheader yokiPUT/DELETEbilan) yuborishdan oldin, brauzer avtomatikOPTIONSso'rovini yuboradi ("bu so'rovga ruxsat bormi?" — 2.10 CORS). ServerAccess-Control-Allow-*header'lari bilan204qaytaradi (ruxsat berildi), keyin brauzer asosiy so'rovni yuboradi. Public API'da (boshqa domendanPUT/DELETEkelsa)OPTIONShandler majburiy; (2)HEAD—GETkabi, 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.jsGEThandler'ni statik deb hisoblaydi (build vaqtida bir marta bajarib, natijani keshlaydi) — agar urequest/searchParams/cookies/headersishlatmasa. Agar ishlatsa (masalannew 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/DELETEhech qachon keshlanmaydi (mutation — har doim bajariladi). Ikki nuqta: (1)OPTIONS— CORS preflight (brauzer avtomatik — public API'da kerak),HEAD— faqat header (mavjudlik/hajm); (2)GETstatik keshlanadi (tez), lekinrequest/searchParams/cookieso'qisa yokiforce-dynamicbo'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
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 fonRate 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 oshsasuccess: false— server429 Too Many Requestsqaytaradi. 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 —429status (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
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 : 4294. 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.
// 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.
// 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.
// 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 tekshir — verifyStripeSignature(...) (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.
// 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.
// 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 tekshir — locales.some(...) (/uz/, /en/ bilan boshlanadimi); agar bor — next() (davom — til allaqachon to'g'ri); (2) til yo'q bo'lsa aniqla — request.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.
// 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=2Bu 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).
// 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'lBu 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.
// 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.
// 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.
// 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) autentifikatsiya — getServerSession() (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) mutation — try/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 boshqaruvi — catch 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.
// 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.
// 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 aniqlash — x-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
Route Handler + client fetch (keraksiz murakkab — 2.6)
Server Action (soddaroq — Misol 9)2) Tashqi mijoz uchun
Server Action (mobil/webhook chaqira olmaydi — 2.6)
Route Handler (REST — universal — Misol 3)3) Status kodlar
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
middleware'da DB so'rov (edge — sekin, cheklangan — 2.9)
middleware yengil (auth/redirect); DB — Route Handler nodejs5) matcher
matcher yo'q (middleware har so'rovga — statik ham — sekin)
matcher (faqat kerakli yo'l — 2.8)6) Webhook xavfsizligi
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)
- REST API: posts CRUD (collection + [id] — Misol 1, 2).
- Status kodlar: 201/400/401/404/500 to'g'ri 2.2-bob.
- Auth API: himoyalangan endpoint (session — Misol 10).
- Validatsiya: Zod har POST/PUT'da (Misol 10).
- Auth middleware: /dashboard himoya (Misol 4).
- i18n yoki xavfsizlik header: middleware (Misol 5 yoki 7).
- matcher: to'g'ri nishonlash 2.8-bob.
- Webhook: imzo tekshir (Misol 3).
- Query API: filtr/saralash/sahifalash (Misol 6).
- 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!