12 β Express asoslari¶
β¬ οΈ Oldingi: 11 β HTTP moduli: native server (sehrsiz) Β· π README Β· Keyingi: 13 β Middleware β‘οΈ
Bu bobda: 11-bobda native
httpmoduli bilan server qurdik va tezda sezdik β metodni, URL'ni, so'rov tanasini, headerlarni hammasini qo'lda boshqarish charchatadi. Endi Express.js bilan tanishamiz: Node ekotizimidagi eng mashhur veb-framework. U aynan o'sha takrorlanuvchi "boshqaruv kodi"ni yashiradi va sizga toza, deklarativ marshrutlash (routing), so'rov tanasini avtomatik o'qish va qulay javob metodlarini beradi. O'rnatish (npm install express), minimal app,app.get/post/put/delete, route parametrlari (:id), query string,express.json()bilanreq.body,res.json/status/send/redirect, marshrutlarniexpress.Router()bilan alohida fayllarga bo'lish, statik fayllar (express.static) β hammasini ko'ramiz. So'ng nativehttpbilan yonma-yon solishtiramiz va Fastify/NestJS alternativalarini qisqa eslab o'tamiz. Real misol β vazifalar (todo) REST API, ishlaydigan va to'liq.
Nega Express? Native http ning og'rig'i¶
11-bobda biz bitta JSON endpoint yozish uchun shunga o'xshash kod yozdik:
import { createServer } from "node:http";
const server = createServer((req, res) => {
if (req.method === "GET" && req.url === "/vazifalar") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify([{ id: 1, matn: "test" }]));
return;
}
res.writeHead(404, { "Content-Type": "application/json" });
res.end(JSON.stringify({ xato: "Topilmadi" }));
});
server.listen(3000);
Bu ishlaydi. Lekin har bir yangi yo'l uchun yana bitta if qo'shiladi, har bir javobda Content-Type ni o'zingiz yozasiz, POST tanasini o'qish uchun data/end hodisalarini qo'lda yig'asiz, va /users/:id kabi parametrli yo'l uchun esa URL'ni o'zingiz bo'laklarga ajratasiz. Ilova o'sgani sari bu kod bir nechta o'nlab iflarga aylanadi β o'qib bo'lmaydigan, xato osongina kiradigan tugunga.
Express shu muammoni hal qiladi. U native http ustiga qurilgan yupqa qatlam (thin layer): tagida baribir o'sha http.createServer ishlaydi, lekin Express sizga uchta katta qulaylikni beradi:
- Routing β "GET /vazifalar bo'lsa, mana bu funksiya" deb deklarativ aytasiz; metod va URL solishtirishni Express qiladi.
- Body parsing β
express.json()middleware so'rov tanasini avtomatik o'qibreq.bodyga JS obyekt qilib qo'yadi. - Qulay javob metodlari β
res.json(obj)headerni ham,JSON.stringifyni ham o'zi qiladi;res.status(201)zanjirlanadi.
Natijada yuqoridagi 12 qatorlik native kod Express'da uch qatorga aylanadi (buni bob oxirida yonma-yon ko'rasiz). Siz niyatni yozasiz, mexanizmni Express yashiradi.
Yana bir muhim narsa β Express ulkan ekotizim: autentifikatsiya, sessiya, fayl yuklash, shablonlar uchun minglab tayyor middleware'lar bor. "Node'da backend" deganda ko'pchilik avval Express'ni nazarda tutadi. Shuning uchun u o'rganish uchun ideal birinchi framework.
Eslatma: Express β "sehr" emas. U faqat siz qiladigan ishni qisqartiradi. 11-bobni o'tganingiz uchun siz tagida nima bo'layotganini bilasiz β bu sizni "sehrga ishonadigan" emas, "mexanizmni tushunadigan" dasturchi qiladi.
O'rnatish va minimal ilova¶
Express tashqi paket β Node bilan kelmaydi, npm orqali o'rnatiladi. Avval loyiha papkasini tayyorlaymiz:
npm install express node_modules/ ichiga Express va uning bog'liqliklarini joylaydi va package.json ga qo'shadi. Biz zamonaviy ESM (import/export) uslubidan foydalanamiz, shuning uchun package.json ga "type": "module" qo'shamiz:
{
"name": "vazifalar-api",
"version": "1.0.0",
"type": "module",
"dependencies": {
"express": "^5.1.0"
}
}
CommonJS farqi: agar
"type": "module"qo'ymasangiz (eski uslub), import o'rnigaconst express = require("express")yozasiz. Bu bobda hamma joyda ESMimport express from "express"ishlatamiz β Node 20+ va Express 5 da bu standart.
Endi eng kichik ishlaydigan server:
// app.mjs
import express from "express";
const app = express(); // ilova obyektini yaratamiz
app.get("/", (req, res) => { // GET / so'rovini tinglaymiz
res.send("Salom, Express!"); // javob yuboramiz
});
app.listen(3000, () => { // 3000-portda tinglashni boshlaymiz
console.log("Server tayyor: http://localhost:3000");
});
Ishga tushiramiz:
Brauzerda http://localhost:3000 ni oching yoki boshqa terminalda tekshiring. Uch tushuncha:
express()β markaziy ilova obyekti. Bu funksiya, lekin undaget,post,use,listenkabi metodlar bor.app.get(yo'l, handler)β "GET metodli, shu yo'lga kelgan so'rovni mana bu funksiya bilan ishla" deb ro'yxatdan o'tkazadi.handlerβ(req, res)qabul qiluvchi funksiya.app.listen(port, callback)β tagidagihttpserverni ishga tushiradi. Bu nativehttp.Serverβ Express uni o'rab beradi xolos.
Serverni kod bilan tekshirish¶
Butun bob davomida biz serverni ishga tushirib, o'sha jarayon ichida Node 24 ning global fetch funksiyasi bilan so'rov yuboramiz va javobni tekshiramiz. Bu β kodni haqiqatan ishlashiga ishonch hosil qilishning eng to'g'ri yo'li:
// minimal.mjs β ishga tushiring: node minimal.mjs
import express from "express";
const app = express();
app.get("/", (req, res) => {
res.send("Salom, Express!");
});
const server = app.listen(3000, async () => {
const r = await fetch("http://localhost:3000/");
console.log("Status:", r.status);
console.log("Body:", await r.text());
server.close(); // tekshirib bo'lib serverni yopamiz
});
server.close() serverni to'xtatadi β aks holda jarayon abadiy tinglab turaverardi. Real ilovada close qilmaysiz (server doim ishlasin), lekin tekshiruv skriptida bu qulay.
Routing: metod va yo'l bo'yicha marshrutlash¶
Routing β "qaysi so'rov qaysi funksiyaga boradi" degan masala. Express har bir HTTP metod uchun bir xil nomli metod beradi:
app.get("/vazifalar", handler); // ro'yxatni o'qish
app.post("/vazifalar", handler); // yangi qo'shish
app.put("/vazifalar/:id", handler); // to'liq yangilash
app.patch("/vazifalar/:id", handler); // qisman yangilash
app.delete("/vazifalar/:id", handler); // o'chirish
Bu nomlar bejiz emas β ular REST konvensiyasiga mos keladi: GET o'qish, POST yaratish, PUT/PATCH yangilash, DELETE o'chirish uchun. Bir xil yo'l (/vazifalar) turli metodlar uchun turli handlerga ega bo'lishi mumkin β Express metod va yo'lni birga solishtiradi.
app.use(...) esa maxsus β u barcha metodlar uchun ishlaydi va asosan middleware ulash uchun (13-bobda chuqur ko'ramiz). Hozircha bilib qo'ying: app.use(express.json()) har bir so'rovga JSON o'qishni ulaydi.
Diagrammada ko'rinib turibdi: har bir so'rov zanjirdan o'tadi β avval middleware (masalan express.json()), so'ng router to'g'ri handlerni topadi, handler javob qaytaradi. Bu β Express'ning yadro modeli.
Handler funksiyasi: req va res¶
Har bir handler ikkita asosiy obyekt oladi:
req(request) β kiruvchi so'rov:req.method,req.url,req.params,req.query,req.body,req.headers.res(response) β chiquvchi javob:res.json(),res.status(),res.send(),res.set(),res.redirect().
Bu obyektlar native http ning req/res larini kengaytiradi β ya'ni 11-bobda ko'rgan res.end() hali ham mavjud, lekin Express ustiga qulayroq metodlar qo'shadi.
Route parametrlari, query va so'rov tanasi¶
Endi Express'ning eng ko'p ishlatiladigan uchta kirish manbasini ko'ramiz: yo'l parametrlari, query string va so'rov tanasi.
Route parametrlari β req.params¶
Yo'lda :nom ko'rinishidagi qism β bu parametr (o'zgaruvchan bo'lak). Express uni ajratib req.params ga qo'yadi:
app.get("/users/:id", (req, res) => {
res.json({ id: req.params.id, type: typeof req.params.id });
});
/users/42 so'rovi quyidagini qaytaradi:
Diqqat:
req.params.iddoim satr ("42", raqam emas). Agar sonli taqqoslash kerak bo'lsa,Number(req.params.id)bilan o'giring β bu keng tarqalgan xato manbai.
Query string β req.query¶
URL'dagi ? dan keyingi qism β query: /search?q=node&limit=5. Express uni obyektga aylantirib req.query ga qo'yadi:
/search?q=node&limit=5 β
Query qiymatlari ham satr bo'ladi. Query odatda filtrlash, sahifalash, qidiruv uchun ishlatiladi (masalan ?bajarildi=true&sahifa=2).
So'rov tanasi β express.json() va req.body¶
POST/PUT so'rovlarida ma'lumot tanada (body) keladi. Native httpda buni data/end hodisalari bilan qo'lda yig'ardik. Express'da bitta middleware shuni qiladi:
Endi handlerda req.body tayyor:
Bu uchta misolni birga ishga tushirib tekshiramiz:
// routing.mjs β node routing.mjs
import express from "express";
const app = express();
app.use(express.json()); // tanani o'qish uchun MUHIM
app.get("/users/:id", (req, res) => {
res.json({ id: req.params.id, type: typeof req.params.id });
});
app.get("/search", (req, res) => {
res.json({ q: req.query.q, limit: req.query.limit });
});
app.post("/echo", (req, res) => {
res.status(201).json({ qabulQilindi: req.body });
});
const server = app.listen(3000, async () => {
const base = "http://localhost:3000";
const a = await fetch(`${base}/users/42`);
console.log("params:", await a.json());
const b = await fetch(`${base}/search?q=node&limit=5`);
console.log("query:", await b.json());
const c = await fetch(`${base}/echo`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ism: "Oqil", yosh: 30 }),
});
console.log("status:", c.status, "body:", await c.json());
server.close();
});
params: { id: '42', type: 'string' }
query: { q: 'node', limit: '5' }
status: 201 body: { qabulQilindi: { ism: 'Oqil', yosh: 30 } }
Tez-tez uchraydigan xato:
express.json()niapp.usebilan ulashni unutsangiz,req.bodyundefinedbo'ladi va dastur "yiqiladi". POST/PUT bilan ishlasangiz β bu qatorni har doim qo'shing.
res metodlari: javobni yuborish¶
res obyekti javobni shakllantiradi. Eng muhim metodlar:
| Metod | Vazifa |
|---|---|
res.json(obj) |
Obyektni JSON qilib yuboradi (Content-Type: application/json o'zi qo'yiladi) |
res.send(str) |
Matn/HTML/Buffer yuboradi |
res.status(kod) |
Status kodini o'rnatadi (zanjirlanadi: res.status(201).json(...)) |
res.sendStatus(kod) |
Status + shu kodning standart matnini yuboradi (404 β "Not Found") |
res.set(nom, qiymat) |
Javob headerini o'rnatadi |
res.redirect(yo'l) |
Boshqa manzilga yo'naltiradi (302) |
Hammasi bitta serverda:
// res-metodlar.mjs β node res-metodlar.mjs
import express from "express";
const app = express();
app.get("/teapot", (req, res) => {
res.set("X-Powered-By", "Express-kitob"); // header qo'yamiz
res.status(418).send("Men choynakman"); // status + matn
});
app.get("/yoq", (req, res) => {
res.sendStatus(404); // "Not Found" matni avtomatik
});
app.get("/eski", (req, res) => {
res.redirect("/yangi"); // 302 yo'naltirish
});
const server = app.listen(3000, async () => {
const base = "http://localhost:3000";
const d = await fetch(`${base}/teapot`);
console.log("teapot:", d.status, d.headers.get("X-Powered-By"), await d.text());
const e = await fetch(`${base}/yoq`);
console.log("sendStatus:", e.status, await e.text());
const f = await fetch(`${base}/eski`, { redirect: "manual" });
console.log("redirect:", f.status, f.headers.get("location"));
server.close();
});
res.jsonvsres.send: obyekt yuborayotgan bo'lsangiz β doimres.json(). UContent-Typeni to'g'ri qo'yadi vaJSON.stringifyni o'zi qiladi.res.send()ga obyekt bersangiz, Express baribir JSON qiladi, lekin niyatni aniq bildirgani uchunres.jsonafzal.
Bir handler ikki marta javob bermasligi kerak. res.json(...) dan keyin yana res.send(...) chaqirsangiz, Express "Cannot set headers after they are sent" xatosini beradi. Shuning uchun ko'pincha return res.status(404).json(...) yozamiz β return qolgan kodni to'xtatadi.
REAL KEYS: vazifalar REST API (CRUD)¶
Endi nazariyani haqiqiy, ishlaydigan REST API ga aylantiramiz: oddiy "vazifalar ro'yxati" (todo). Ma'lumotni hozircha xotiradagi massivda saqlaymiz (baza 14-bobdan boshlanadi). API to'rtta amalni qo'llaydi:
| Metod + yo'l | Vazifa |
|---|---|
GET /vazifalar |
Hammasini qaytaradi |
GET /vazifalar/:id |
Bittasini qaytaradi |
POST /vazifalar |
Yangi qo'shadi |
PUT /vazifalar/:id |
Mavjudini yangilaydi |
DELETE /vazifalar/:id |
O'chiradi |
Avval hammasini bitta faylga yozsa ham bo'lardi, lekin marshrutlarni alohida modulga ajratish β professional odat. Buni express.Router() bilan qilamiz.
express.Router() β marshrutlarni modulga bo'lish¶
Router β "mini-ilova": uning ham get/post/put/delete metodlari bor, lekin u app emas, alohida marshrut to'plami. Uni alohida faylda yaratib, app ga ulaymiz. Bu kodni toza, modulli va sinov qilish oson saqlaydi.
vazifalar.router.mjs β faqat vazifalar marshrutlari:
// vazifalar.router.mjs
import { Router } from "express";
export const vazifalarRouter = Router();
// In-memory "ma'lumotlar bazasi" (vaqtinchalik massiv)
let vazifalar = [
{ id: 1, matn: "Express o'rganish", bajarildi: false },
{ id: 2, matn: "REST API yozish", bajarildi: false },
];
let keyingiId = 3;
// GET /vazifalar -> hammasi
vazifalarRouter.get("/", (req, res) => {
res.json(vazifalar);
});
// GET /vazifalar/:id -> bittasi
vazifalarRouter.get("/:id", (req, res) => {
const id = Number(req.params.id);
const v = vazifalar.find((x) => x.id === id);
if (!v) return res.status(404).json({ xato: "Vazifa topilmadi" });
res.json(v);
});
// POST /vazifalar -> yangi qo'shish
vazifalarRouter.post("/", (req, res) => {
const { matn } = req.body ?? {};
if (!matn || typeof matn !== "string") {
return res.status(400).json({ xato: "matn (string) majburiy" });
}
const yangi = { id: keyingiId++, matn, bajarildi: false };
vazifalar.push(yangi);
res.status(201).json(yangi);
});
// PUT /vazifalar/:id -> yangilash
vazifalarRouter.put("/:id", (req, res) => {
const id = Number(req.params.id);
const v = vazifalar.find((x) => x.id === id);
if (!v) return res.status(404).json({ xato: "Vazifa topilmadi" });
if (typeof req.body.matn === "string") v.matn = req.body.matn;
if (typeof req.body.bajarildi === "boolean") v.bajarildi = req.body.bajarildi;
res.json(v);
});
// DELETE /vazifalar/:id -> o'chirish
vazifalarRouter.delete("/:id", (req, res) => {
const id = Number(req.params.id);
const bormi = vazifalar.some((x) => x.id === id);
if (!bormi) return res.status(404).json({ xato: "Vazifa topilmadi" });
vazifalar = vazifalar.filter((x) => x.id !== id);
res.sendStatus(204); // No Content
});
E'tibor bering: router ichida yo'llar "/" va "/:id" β ya'ni /vazifalar prefiksisiz. Prefiksni app ulaganda beramiz. Bu router'ni qayta ishlatishni osonlashtiradi.
server.mjs β app yaratadi va router'ni ulaydi:
// server.mjs
import express from "express";
import { vazifalarRouter } from "./vazifalar.router.mjs";
const app = express();
app.use(express.json()); // tanani o'qish
app.use(express.static("public")); // statik fayllar (keyinroq tushuntiramiz)
app.use("/vazifalar", vazifalarRouter); // /vazifalar/* -> router'ga
app.get("/", (req, res) => res.send("Vazifalar API ishlayapti"));
app.listen(3000, () => {
console.log("Server: http://localhost:3000");
});
app.use("/vazifalar", vazifalarRouter) β sehrli qator: "/vazifalar bilan boshlanadigan har bir so'rovni shu router'ga uzat". Shuning uchun router ichidagi "/" aslida /vazifalar, "/:id" esa /vazifalar/:id bo'ladi.
To'liq sinov: barcha CRUD amallari¶
Quyida butun API ni fetch bilan boshidan oxirigacha sinaymiz β bu kod haqiqatan ishlaydi (Node 24 + Express 5 da tekshirilgan):
// sinov.mjs β server.mjs dagi app ni eksport qilib, fetch bilan sinaymiz
import express from "express";
import { vazifalarRouter } from "./vazifalar.router.mjs";
const app = express();
app.use(express.json());
app.use("/vazifalar", vazifalarRouter);
const server = app.listen(3000, async () => {
const base = "http://localhost:3000/vazifalar";
console.log("GET hammasi:", await (await fetch(base)).json());
const yangi = await fetch(base, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ matn: "Mashqlarni yechish" }),
});
const qoshilgan = await yangi.json();
console.log("POST yangi:", yangi.status, qoshilgan);
const put = await fetch(`${base}/${qoshilgan.id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ bajarildi: true }),
});
console.log("PUT:", put.status, await put.json());
const yoq = await fetch(`${base}/999`);
console.log("GET /999:", yoq.status, await yoq.json());
const del = await fetch(`${base}/2`, { method: "DELETE" });
console.log("DELETE /2 status:", del.status);
console.log("Oxirgi ro'yxat:", await (await fetch(base)).json());
const xato = await fetch(base, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ notogri: 1 }),
});
console.log("POST validatsiya:", xato.status, await xato.json());
server.close();
});
Natija:
GET hammasi: [
{ id: 1, matn: "Express o'rganish", bajarildi: false },
{ id: 2, matn: 'REST API yozish', bajarildi: false }
]
POST yangi: 201 { id: 3, matn: 'Mashqlarni yechish', bajarildi: false }
PUT: 200 { id: 3, matn: 'Mashqlarni yechish', bajarildi: true }
GET /999: 404 { xato: 'Vazifa topilmadi' }
DELETE /2 status: 204
Oxirgi ro'yxat: [
{ id: 1, matn: "Express o'rganish", bajarildi: false },
{ id: 3, matn: 'Mashqlarni yechish', bajarildi: true }
]
POST validatsiya: 400 { xato: 'matn (string) majburiy' }
Bu β to'liq, professional kichik REST API. E'tibor bering:
- To'g'ri status kodlar: yaratishda
201, o'chirishda204(tana yo'q), topilmaganda404, noto'g'ri kiritishda400. - Validatsiya:
matnbo'lmasa400qaytaramiz, dastur yiqilmaydi. - Modullilik: marshrutlar
appdan alohida faylda βserver.mjsni o'qigan odam darhol "API tarkibi" ni ko'radi.
Statik fayllar β express.static¶
Veb-ilovalar ko'pincha rasm, CSS, JS, HTML kabi statik fayllarni ham berishi kerak. Buni express.static bitta qator bilan hal qiladi:
Bu "loyihaning public/ papkasidagi fayllarni bevosita ber" degani. Agar public/index.html bo'lsa, http://localhost:3000/index.html (yoki /) uni qaytaradi; public/logo.png β /logo.png. Express fayl turini aniqlab to'g'ri Content-Type ni o'zi qo'yadi.
Native httpda buni o'zingiz qilardingiz: URL'dan fayl yo'lini hisoblash, faylni o'qish, MIME turini topish, fayl yo'qligini tekshirish. express.static shuning hammasini bajaradi β bu Express'ning qulayligiga yaqqol misol.
Maslahat: statik fayllar API marshrutlari bilan to'qnashmasligi uchun ularni odatda
/publicyoki/staticprefiks ostiga qo'yish mumkin:app.use("/static", express.static("public")).
Native http bilan solishtirish¶
Endi 11-bob va 12-bobni yonma-yon qo'yamiz. Maqsad bir xil: GET /vazifalar so'roviga JSON ro'yxat qaytarish.
Native http:
import { createServer } from "node:http";
const data = [{ id: 1, matn: "test" }];
const server = createServer((req, res) => {
if (req.method === "GET" && req.url === "/vazifalar") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(data));
return;
}
res.writeHead(404, { "Content-Type": "application/json" });
res.end(JSON.stringify({ xato: "Topilmadi" }));
});
server.listen(3000);
Express:
import express from "express";
const app = express();
const data = [{ id: 1, matn: "test" }];
app.get("/vazifalar", (req, res) => {
res.json(data);
});
app.listen(3000);
Express versiyasida siz metodni va URL'ni tekshirmaysiz (app.get o'zi qiladi), Content-Type qo'ymaysiz (res.json o'zi qo'yadi), JSON.stringify qilmaysiz (res.json o'zi qiladi), va mos kelmaganda 404 β Express o'zi qaytaradi. Bitta endpoint uchun farq kichik ko'rinishi mumkin, lekin 20-30 ta endpoint, parametrlar, body parsing, xatoliklarni boshqarish qo'shilganda Express sizni yuzlab qator takror kod yozishdan qutqaradi.
Lekin tushunib qoling: Express native httpni o'chirmaydi, balki o'rab beradi. app.listen tagida http.createServer chaqiriladi. 11-bobni o'tganingiz uchun Express "sehr" emas, balki siz qiladigan ishni avtomatlashtirilgan ekanini bilasiz β bu sizni har qanday muammoni hal qila oladigan dasturchi qiladi.
Alternativalar: Fastify va NestJS (qisqacha)¶
Express β eng mashhuri, lekin yagonasi emas. Qachon boshqasini o'ylash kerakligini bilib qo'ying:
-
Fastify β Express'ga juda o'xshash, lekin tezroq (yuqori ishlash) va sxema-asoslangan validatsiyani tabiiy qo'llaydi (JSON Schema bilan so'rov/javobni tekshirish). Agar yuqori yuklamali API yozsangiz yoki validatsiya muhim bo'lsa β Fastify yaxshi tanlov. API'si Express'ga yaqin, shuning uchun ko'chish oson.
-
NestJS β bu to'liq freymvork (Angular ruhida): TypeScript, dekoratorlar (
@Controller,@Get), dependency injection, modullar tizimi. U katta, ko'p odamlik, uzoq muddatli korporativ loyihalar uchun tuzilma beradi. Tagida odatda Express (yoki Fastify) ishlaydi. Boshlang'ich loyiha uchun ortiqcha β lekin loyiha o'sganda struktura zarur bo'lsa, NestJS qutqaradi.
Tavsiya: o'rganish va aksariyat loyihalar uchun Express'dan boshlang. U eng katta ekotizimga, eng ko'p o'quv materialiga ega. Fastify/NestJS β keyinchalik, aniq ehtiyoj paydo bo'lganda. Express'da o'rgangan tushunchalar (routing, middleware, req/res) ikkalasiga ham deyarli to'g'ridan-to'g'ri ko'chadi.
Mashqlar¶
Oson¶
-
Express ilovasi yarating:
GET /salomso'roviga{ "xabar": "Assalomu alaykum" }JSON qaytarsin.res.jsonishlating vafetchbilan tekshiring. -
GET /yor/:ismmarshrutini yozing β/yor/Oqilso'roviga matn sifatida"Salom, Oqil!"qaytarsin (req.params.ismdan foydalaning). -
GET /qoshish?a=5&b=3marshrutini yozing βreq.querydanavabni olib, yig'indisini JSON qaytarsin. Eslang: query qiymatlari satr,Number()kerak.
O'rta¶
-
POST /salomlashmarshrutini yozing: tanada{ "ism": "..." }keladi, javobda{ "xabar": "Salom, <ism>!" }qaytsin.express.json()ni ulashni unutmang. Agarismbo'lmasa,400va xato xabarini qaytaring. -
vazifalarAPI'ga query bilan filtrlash qo'shing:GET /vazifalar?bajarildi=truefaqat bajarilgan vazifalarni qaytarsin. Query bo'lmasa β hammasini. (Eslatma:req.query.bajarildisatr"true"bo'ladi.) -
vazifalar.router.mjsni alohida fayl qilibserver.mjsga ulang, so'ng yana bitta router βsalom.router.mjs(faqatGET /β matn) yarating va uniapp.use("/salom", salomRouter)bilan ulang. Ikkita mustaqil router bir ilovada ishlashini ko'rsating.
Qiyin¶
-
To'liq vazifalar REST API yozing (xotirada massiv):
GET /vazifalar,GET /vazifalar/:id,POST /vazifalar,PUT /vazifalar/:id,DELETE /vazifalar/:id. To'g'ri status kodlardan foydalaning (201yaratishda,204o'chirishda,404topilmaganda,400noto'g'ri kiritishda), marshrutlarniexpress.Router()bilan alohida faylga ajrating, va butun API'nifetchbilan boshdan-oxir sinab natijani konsolga chiqaring. -
app.route("/element/:id")zanjiri bilan bir yo'lga.get()va.delete()ni biriktiring. So'ng kichik so'rovchi-sanagich middleware yozing (app.use((req, res, next) => {...})) β u har so'rovdareq.metodvareq.urlni konsolga chiqarsin, keyinnext()chaqirsin. Middleware barcha marshrutlardan oldin ishlashini tekshiring.
Yechim β 1
Yechim β 2
import express from "express";
const app = express();
app.get("/yor/:ism", (req, res) => {
res.send(`Salom, ${req.params.ism}!`);
});
const server = app.listen(3000, async () => {
const r = await fetch("http://localhost:3000/yor/Oqil");
console.log(await r.text());
server.close();
});
req.params.ism β yo'ldagi :ism o'rniga kelgan qism.
Yechim β 3
import express from "express";
const app = express();
app.get("/qoshish", (req, res) => {
const a = Number(req.query.a);
const b = Number(req.query.b);
res.json({ a, b, yigindi: a + b });
});
const server = app.listen(3000, async () => {
const r = await fetch("http://localhost:3000/qoshish?a=5&b=3");
console.log(await r.json());
server.close();
});
Number() siz "5" + "3" "53" satriga aylanardi β bu keng xato.
Yechim β 4
import express from "express";
const app = express();
app.use(express.json()); // tanani o'qish uchun MUHIM
app.post("/salomlash", (req, res) => {
const { ism } = req.body ?? {};
if (!ism) {
return res.status(400).json({ xato: "ism majburiy" });
}
res.json({ xabar: `Salom, ${ism}!` });
});
const server = app.listen(3000, async () => {
const ok = await fetch("http://localhost:3000/salomlash", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ism: "Laylo" }),
});
console.log("ok:", ok.status, await ok.json());
const yomon = await fetch("http://localhost:3000/salomlash", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
});
console.log("xato:", yomon.status, await yomon.json());
server.close();
});
req.body ?? {} β agar express.json() ulanmagan yoki tana bo'sh bo'lsa ham "yiqilmaslik" uchun.
Yechim β 5
import express from "express";
const app = express();
app.use(express.json());
let vazifalar = [
{ id: 1, matn: "a", bajarildi: true },
{ id: 2, matn: "b", bajarildi: false },
{ id: 3, matn: "c", bajarildi: true },
];
app.get("/vazifalar", (req, res) => {
let natija = vazifalar;
if (req.query.bajarildi !== undefined) {
const want = req.query.bajarildi === "true"; // satrni boolean'ga
natija = vazifalar.filter((v) => v.bajarildi === want);
}
res.json(natija);
});
const server = app.listen(3000, async () => {
const f = await fetch("http://localhost:3000/vazifalar?bajarildi=true");
console.log("filtr:", await f.json());
const hammasi = await fetch("http://localhost:3000/vazifalar");
console.log("soni:", (await hammasi.json()).length);
server.close();
});
Asosiy nuqta: query qiymati satr, shuning uchun === "true" bilan boolean'ga aylantiramiz. !== undefined tekshiruvi query umuman berilmaganini ajratadi.
Yechim β 6
salom.router.mjs:
import { Router } from "express";
export const salomRouter = Router();
salomRouter.get("/", (req, res) => res.send("Salom router'dan!"));
vazifalar.router.mjs:
import { Router } from "express";
export const vazifalarRouter = Router();
const vazifalar = [{ id: 1, matn: "test" }];
vazifalarRouter.get("/", (req, res) => res.json(vazifalar));
server.mjs:
import express from "express";
import { salomRouter } from "./salom.router.mjs";
import { vazifalarRouter } from "./vazifalar.router.mjs";
const app = express();
app.use("/salom", salomRouter);
app.use("/vazifalar", vazifalarRouter);
const server = app.listen(3000, async () => {
console.log("salom:", await (await fetch("http://localhost:3000/salom")).text());
console.log("vazifalar:", await (await fetch("http://localhost:3000/vazifalar")).json());
server.close();
});
Har bir router o'z prefiksi ostida mustaqil ishlaydi. Bu β katta ilovalarni boshqarish usuli: har bir resurs (/foydalanuvchilar, /buyurtmalar, ...) o'z fayliga.
Yechim β 7
vazifalar.router.mjs (modul):
import { Router } from "express";
export const vazifalarRouter = Router();
let vazifalar = [
{ id: 1, matn: "Express o'rganish", bajarildi: false },
{ id: 2, matn: "REST API yozish", bajarildi: false },
];
let keyingiId = 3;
vazifalarRouter.get("/", (req, res) => res.json(vazifalar));
vazifalarRouter.get("/:id", (req, res) => {
const id = Number(req.params.id);
const v = vazifalar.find((x) => x.id === id);
if (!v) return res.status(404).json({ xato: "Topilmadi" });
res.json(v);
});
vazifalarRouter.post("/", (req, res) => {
const { matn } = req.body ?? {};
if (!matn || typeof matn !== "string") {
return res.status(400).json({ xato: "matn (string) majburiy" });
}
const yangi = { id: keyingiId++, matn, bajarildi: false };
vazifalar.push(yangi);
res.status(201).json(yangi);
});
vazifalarRouter.put("/:id", (req, res) => {
const id = Number(req.params.id);
const v = vazifalar.find((x) => x.id === id);
if (!v) return res.status(404).json({ xato: "Topilmadi" });
if (typeof req.body.matn === "string") v.matn = req.body.matn;
if (typeof req.body.bajarildi === "boolean") v.bajarildi = req.body.bajarildi;
res.json(v);
});
vazifalarRouter.delete("/:id", (req, res) => {
const id = Number(req.params.id);
if (!vazifalar.some((x) => x.id === id)) {
return res.status(404).json({ xato: "Topilmadi" });
}
vazifalar = vazifalar.filter((x) => x.id !== id);
res.sendStatus(204);
});
server.mjs (sinov bilan):
import express from "express";
import { vazifalarRouter } from "./vazifalar.router.mjs";
const app = express();
app.use(express.json());
app.use("/vazifalar", vazifalarRouter);
const server = app.listen(3000, async () => {
const base = "http://localhost:3000/vazifalar";
const yangi = await fetch(base, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ matn: "Yangi ish" }),
});
const q = await yangi.json();
console.log("POST:", yangi.status, q);
const put = await fetch(`${base}/${q.id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ bajarildi: true }),
});
console.log("PUT:", put.status, await put.json());
const del = await fetch(`${base}/1`, { method: "DELETE" });
console.log("DELETE status:", del.status);
const yoq = await fetch(`${base}/999`);
console.log("404:", yoq.status, await yoq.json());
console.log("Oxiri:", await (await fetch(base)).json());
server.close();
});
POST: 201 { id: 3, matn: 'Yangi ish', bajarildi: false }
PUT: 200 { id: 3, matn: 'Yangi ish', bajarildi: true }
DELETE status: 204
404: 404 { xato: 'Topilmadi' }
Oxiri: [
{ id: 2, matn: 'REST API yozish', bajarildi: false },
{ id: 3, matn: 'Yangi ish', bajarildi: true }
]
Diqqat qiling: har bir "topilmadi" holatida return res.status(404)... β return qolgan handlerni to'xtatadi, aks holda ikki marta javob yuborishga urinib, dastur xato berardi. Status kodlar REST konvensiyasiga mos: yaratish 201, o'chirish 204 (tanasiz), validatsiya 400, topilmaslik 404.
Yechim β 8
import express from "express";
const app = express();
// 1) so'rovchi-sanagich middleware β BARCHA marshrutdan oldin
app.use((req, res, next) => {
console.log(`[log] ${req.method} ${req.url}`);
next(); // next() chaqirilmasa, oqim shu yerda to'xtaydi!
});
// 2) app.route bilan bir yo'lga ko'p metod
app
.route("/element/:id")
.get((req, res) => res.json({ olindi: req.params.id }))
.delete((req, res) => res.sendStatus(204));
const server = app.listen(3000, async () => {
const g = await fetch("http://localhost:3000/element/9");
console.log("get:", await g.json());
const d = await fetch("http://localhost:3000/element/9", { method: "DELETE" });
console.log("delete status:", d.status);
server.close();
});
Ikki tushuncha: app.route("/yo'l") bir yo'lga turli metodlarni zanjir qilib biriktiradi β yo'lni takror yozmaysiz. Middleware (app.use(fn)) har bir so'rovda, marshrutdan oldin ishlaydi; next() chaqirib navbatni keyingisiga uzatadi. Agar next() ni unutsangiz, so'rov "osilib" qoladi β bu 13-bobning asosiy mavzusi.
β¬ οΈ Oldingi: 11 β HTTP moduli: native server (sehrsiz) Β· π README Β· Keyingi: 13 β Middleware β‘οΈ