Mundarija (23)
- Bu darsda
- 1. Nega bu kerak?
- 2. Express nima
- 2.1 app — oddiy funksiya
- 2.2 Express nimani qo'shadi
- 3. Express 5
- 3.1 Qisqa tarix
- 3.2 4 dan 5 ga: nima o'zgardi
- 4. Birinchi Express server
- 4.1 O'rnatish
- 4.2 Server va sukut xulqlari
- 5. Narxi: o'lchov
- 5.1 Muqobillar
- 6. API qadami: Express'ga ko'chish (holat 13, 1-qism)
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): to'ldiring
- 2-mashq (o'rta): o'z "kichik Express"ingiz
- 3-mashq (qiyin): 405 bilan Express
- 4-mashq: API qadami
- 9. Real ishda
- Xulosa
- Manbalar
Express.js'ga kirish: Express 5, app.get va app.listen, node:http ustidagi yupqa qatlam
Qisqacha: Express —
node:httpustidagi yupqa kutubxona. U ikki narsa qo'shadi: routing (app.get("/yol", ishlovchi)) va middleware zanjiri.express()qaytarganapp— oddiy(req, res)funksiyasi, unihttp.createServer(app)ga berish mumkin. 2026-10 holatiga npm'dagi joriy versiya — Express 5.3.0 (Node 18+ talab qiladi). Narxi ham bor. Biz o'lchadik: 65 paket, sovuq start 171 → 289 ms. Kichik JSON javobda tezlik 27 096 → 9 724 req/s ga tushdi.
Bu darsda
- Express nima qo'shishini va nimani qo'shmasligini
node:httpkodimiz bilan solishtirib ko'rasiz. express(),app.get/post,app.listenbilan birinchi Express serverini yozasiz.- Express 5 tarixini va Node 18+ talabini bilasiz.
- Express sukut bo'yicha qo'yadigan narsalarni (
X-Powered-By,ETag, HTML 404,HEAD) ko'rasiz. vazifalar-apini Express'ga ko'chirishni boshlaysiz.
Oldin bilishingiz kerak: Qo'lda routing va query parametrlar, Request body o'qish va hajm cheklovi, Static fayl server, Server timeout'lari.
1. Nega bu kerak?
Holat 07 dagi src/ilova.ts ni eslang. U ishlaydi va testlardan o'tadi, lekin unda takrorlanadigan "quvur" kodi ko'p:
- routing —
if (url.pathname === "/vazifalar"), keyin regex/^\/vazifalar\/(\d+)$/, ichidaif (metod === "GET")zanjiri; - javob yordamchisi —
json(res, holat, malumot):Content-Type,Content-Length,JSON.stringify; - tana o'qish —
jsonTana(req): 415, 413, 400; - static fayllar —
statik.ts, 70 qator; - xato ishlash —
yonalt(req, res).catch(...).
Bu kod har API'da deyarli bir xil. Yangi resurs (/teglar, /eksportlar) qo'shilsa, if zanjiri uzayadi. Bu yerda framework — tayyor karkas — yordam beradi. Node dunyosida eng ko'p ishlatiladigani — Express.
O'xshatish: uy qurish. node:http — g'isht, sement, quvurlar. Hammasini o'zingiz terasiz va har bir g'ishtni bilasiz. Express — tayyor karkas: devorlar va quvurlar o'rnatilgan, siz xonalarni bezaysiz. Oldingi to'rt darsda g'ishtdan qurdik — endi karkas ichida nima borligini bilib turib ishlatamiz.
2. Express nima
2.1 app — oddiy funksiya
Express'ning eng muhim siri bitta qatorda. Biz ishga tushirdik (Express 5.3.0, Node 24.21.0):
import express from "express";
const app = express();
console.log(typeof app, app.length);function 3app — funksiya, uchta parametrli: (req, res, next). Bu xuddi createServer darsidagi ishlovchi — faqat qo'shimcha next bilan. Shuning uchun app ni node:http ga to'g'ridan berish mumkin:
import { createServer } from "node:http";
const server = createServer(app); // app — oddiy ishlovchi
server.listen(3000, "127.0.0.1");app.listen(3000) aynan shu ikki qatorning qisqartmasi: ichida http.createServer(this) va .listen(...). U qaytaradigan qiymat — oddiy http.Server. Ya'ni timeout'lar darsidagi hamma narsa (keepAliveTimeout, closeIdleConnections, yop()) Express bilan ham o'zgarmaydi.
flowchart LR
T["TCP ulanish"] --> H["node:http<br/>req, res"]
H --> A["app(req, res)"]
A --> M["middleware'lar"]
M --> R["marshrut<br/>app.get('/salom')"]
R --> J["res.json()"]Diagrammada Express — o'rtadagi uch quti. Chap tomon (TCP, HTTP tahlili) — Node'ning o'zi, Express unga tegmaydi.
Middleware (oraliq ishlovchi) — so'rov marshrutga yetguncha navbat bilan ishlaydigan funksiya. U req ni o'qiydi yoki to'ldiradi (masalan JSON tanani req.body ga). Keyin next() bilan so'rovni keyingisiga uzatadi yoki o'zi javob beradi. Next.js'dagi proxy.ts (sobiq middleware) bilan g'oya bir xil, lekin Express'da bunday funksiyalar ko'p bo'ladi va zanjir bo'lib ketma-ket turadi. Batafsil — middleware darsida.
2.2 Express nimani qo'shadi
| Imkoniyat | node:http da |
Express'da |
|---|---|---|
| Routing | if + regex |
app.get("/vazifalar/:id", …) |
| Yo'l parametri | m[1] |
req.params.id |
| Query | new URL(...).searchParams |
req.query |
| JSON tana | o'z jsonTana() |
express.json() |
| JSON javob | o'z json() |
res.json() |
| Static fayllar | o'z statik.ts |
express.static() |
| Xato ishlash | .catch |
xato middleware |
Express qo'shmaydigan narsalar ham bor: validatsiya, baza, autentifikatsiya, log, konfiguratsiya. Bular uchun alohida kutubxonalar yoki o'z kodingiz kerak — qismning qolgan darslari shular haqida. Express "minimalist" deb ataladi: u faqat so'rov va javob quvurini beradi.
Tekshirib ko'ring: Express ilovasida
keepAliveTimeoutni 65 s qilish kerak.app.set(...)bilanmi yoki boshqa joydami?
Javob
Express sozlamalari emas — http.Server sozlamasi. Yo createServer({ keepAliveTimeout: 65_000 }, app), yo const server = app.listen(...) dan keyin server.keepAliveTimeout = 65_000. Express HTTP ulanishlarini boshqarmaydi, u faqat har so'rovni qayta ishlaydi.
3. Express 5
3.1 Qisqa tarix
Express 2010 yilda chiqqan. 4-versiya (2014) o'n yil davomida asosiy versiya bo'ldi — internetdagi maqolalar va Stack Overflow javoblarining aksariyati shu versiya uchun. 5.0 uzoq kutildi va 2024-yil 9-sentyabrda chiqdi. 2025-yil 31-martda 5.1.0 bilan Express 5 npm'da sukut (latest) versiyaga aylandi (expressjs.com blogi). Endi npm i express 5-versiyani o'rnatadi.
2026-10-24 holatiga npm'dagi versiya — 5.3.0 (2026-10-09 da chiqqan). package.json dagi talab:
{ "engines": { "node": ">= 18" } }Express 5 Node 18 dan eski versiyalarni qo'llamaydi. Bizda Node 24 — muammo yo'q.
3.2 4 dan 5 ga: nima o'zgardi
To'liq ro'yxat — Express 5 darsida. Hozir faqat sarlavhalar, chunki eski maqolalarda ularga duch kelasiz:
- async xatolar — 5 da
asyncishlovchidagithrowavtomatik ushlanadi. 4 da so'rov osilib qolardi. - yo'l sintaksisi —
/fayl/*va/:id?endi xato beradi; yangi shakllar/fayl/*splatva{/:id}. req.query— faqat o'qiladi (getter).- olib tashlanganlar —
app.del,res.send(status)kabi eski shakllar.
Agar maqolada const express = require("express") va app.get("/*", …) ko'rsangiz — u Express 4 uchun yozilgan. Kursda ESM (import express from "express") va 5-versiya.
4. Birinchi Express server
4.1 O'rnatish
Biz bo'sh papkada ishga tushirdik (Node 24.21.0, npm 11.19.0):
npm i --save-exact express@5.3.0added 65 packages, and audited 66 packages in 5s
29 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilitiesBitta bog'liqlik — 65 paket. Express'ning o'z kodi 97 KB, butun daraxt ~2.2 MB (kanon o'lchovi). --save-exact — ^5.3.0 emas, aniq 5.3.0 yoziladi (semver darsi). TypeScript uchun turlar alohida paketda:
npm i -D --save-exact @types/express@5.0.64.2 Server va sukut xulqlari
import express from "express";
const app = express();
app.get("/salom", (req, res) => {
res.json({ xabar: "salom", yol: req.path });
});
const server = app.listen(0, "127.0.0.1");
await new Promise((ok) => server.once("listening", ok));
const a = `http://127.0.0.1:${server.address().port}`;
const r = await fetch(`${a}/salom`);
for (const [k, v] of r.headers) console.log(`${k}: ${v}`);
console.log(await r.text());
const r2 = await fetch(`${a}/salom`, { method: "PUT" });
console.log(r2.status, await r2.text());
server.closeAllConnections();
server.close();Bu blok express paketini talab qiladi, shuning uchun saytda va bizning tekshiruvchida ishga tushmaydi. O'z papkangizda npm i express@5.3.0 dan keyin node salom.mjs qiling. Biz ishga tushirdik:
connection: keep-alive
content-length: 32
content-type: application/json; charset=utf-8
etag: W/"20-mswYnCwHxrFxFsQpC5H+2Rnh+DU"
keep-alive: timeout=5
x-powered-by: Express
{"xabar":"salom","yol":"/salom"}
404 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot PUT /salom</pre>
</body>
</html>Besh qatorni o'zimiz yozmadik, Express o'zi qo'ydi:
content-type: application/json; charset=utf-8vacontent-length—res.json()ishi.etag: W/"20-…"— Express har javobga ETag hisoblaydi:20— uzunlik (32 bayt, o'n oltilikda), keyin tana hash'i. Static fayl darsidagi ETag'ga o'xshash, lekin mazmundan. Kanonda bu hatto 404 va 422 xato javoblarida ham chiqdi.x-powered-by: Express— "men Express'man". Hujumchiga foydali ma'lumot: qaysi zaifliklarni sinashni bildiradi.app.disable("x-powered-by")bilan o'chiriladi.- 404 HTML sahifa —
Cannot PUT /salom.PUT /salomuchun marshrut yo'q, Express esa yo'l bor-yo'qligini bilmaydi va 404 beradi. To'g'risi — 405 Method Not Allowed +Allowsarlavhasi (qo'lda routing darsi). Express 405 ni o'zi bermaydi — kanon testlari buni topdi, yechim middleware darsida. HEAD— biz faqatapp.getyozdik, lekinHEAD /salomham ishlaydi: ExpressGETishlovchisini chaqiradi va tanani tashlaydi (biz sinadik: 200,content-length: 32).
Diqqat: HTML 404 sahifasi JSON API uchun noqulay: frontend
res.json()qilgandaSyntaxError: Unexpected token '<'oladi (fetch darsi). O'z API'ingizda oxirgi middleware sifatida JSON 404 qo'ying — «API qadami» bo'limida ko'rasiz.
5. Narxi: o'lchov
Framework bepul emas. Kanon holat 07 (node:http) va holat 13 (Express) ni bir xil sharoitda o'lchadi — o'sha mashina, o'sha so'rovlar. Server va yuk beruvchi (autocannon, 10 ulanish × 5 s) bitta kompyuterda, bitta o'lchov:
- node:http (holat 07)27 096 req/s
- Express 5.3.0 (holat 13)9 724 req/s
Manba: Kanon o'lchovi, autocannon 8.0.0, 10 ulanish × 5 s, i5-12500H, Node 24.21.0, bitta mashina, 2026-10-24
Kichik javobda Express ~2.8 marta sekinroq: har so'rov middleware zanjiri, query tahlili, ETag hisoblashdan o'tadi. Katta javobda esa farq yo'qoladi. GET /vazifalar (100 vazifa, 26 KB) — 2 669 va 3 237 req/s. Vaqtning asosiy qismi JSON.stringify va tarmoqqa ketadi, Express qatlami sezilmaydi. Ikkinchi raqam hatto katta — bu shovqin, bitta o'lchovdan xulosa chiqarmang.
Sovuq start (jarayon boshlanishidan "server tayyor" qatorigacha, 10 marta mediana): 171 → 289 ms. Taxminan 118 ms — Express va uning 65 paketini import qilish.
Xulosa: bu narx deyarli har doim to'lanadi. Haqiqiy API'da so'rovning asosiy vaqti bazaga ketadi (millisekundlar), Express qatlami esa mikrosekundlar. Lekin "framework tekin" degan fikr noto'g'ri — biz uni raqam bilan ko'rdik.
5.1 Muqobillar
| Framework | Xususiyati |
|---|---|
| Express | eng keng tarqalgan, minimal, ekotizimi ulkan |
| Fastify | tezlikka qaratilgan, JSON Schema bilan validatsiya |
| Koa | Express mualliflaridan, async middleware |
| Hono | Web standartlari (Request/Response), Node, Bun, Deno, Cloudflare Workers |
| NestJS | Express yoki Fastify ustida to'liq arxitektura (modul, DI) |
Ularni kanonda o'lchamadik — shuning uchun tezlik raqamlari yo'q. NestJS'ni alohida qismda (30-qism) o'rganamiz. Express bilimi hammasiga ko'chadi: so'rov, javob, middleware, marshrut tushunchalari bir xil.
Tekshirib ko'ring: Hamkasbingiz "Express sekin, Fastify'ga o'tamiz" dedi. API'ning har so'rovi bazaga 20 ms ketadi. Nima deysiz?
Javob
Avval o'lchash kerak. Bizning o'lchovda Express qatlami bitta so'rovga taxminan 0.07 ms qo'shadi (1/9 724 − 1/27 096 soniya). 20 ms bazaga nisbatan bu ~0.3 %. Fastify'ga ko'chish bu yerda deyarli foyda bermaydi. Tezlik muammosi bo'lsa — avval bazani optimallashtirish kerak.
6. API qadami: Express'ga ko'chish (holat 13, 1-qism)
Holat 13 besh darsga bo'lingan: bugun Express'ning o'zi, keyin req, res, middleware va Router va qatlamlar. Hali commit qilmang — commit beshinchi darsda.
Bugun loyihani bir qadamda Express'ga o'tkazamiz va testlarni yashil qilamiz. Kod keyingi uch darsda o'zgarmaydi — biz uni qism-qism ochib chiqamiz. Beshinchi darsda esa marshrutlar alohida fayllar va qatlamlarga bo'linadi (kanon holat 13). Bugungi kesim kanonda alohida holat emas: biz uni holat 07 va 13 orasida yig'ib, tekshirdik (Node 24.21.0: tsc 0, ESLint 0, testlar 7/7).
1. O'rnatish — «O'rnatish» bo'limidagi ikki buyruq. package.json da "dependencies": { "express": "5.3.0" } paydo bo'ladi — loyihaning birinchi prod bog'liqligi.
2. O'chiriladigan fayllar. src/statik.ts — uning ishini express.static qiladi: MIME, ETag, Last-Modified, Range/206, 304, traversal himoyasi. src/tana.ts — jsonTana o'rniga express.json({ limit: "16kb" }). HttpXato klassi yangi faylga ko'chadi.
3. Yangi src/umumiy/http-xato.ts (kanon):
// http-xato.ts — status kodli xato (#23 da Problem Details,
// #32 da iyerarxiya bo'ladi)
export class HttpXato extends Error {
readonly holat: number;
constructor(holat: number, xabar: string) {
super(xabar);
this.name = "HttpXato";
this.holat = holat;
}
}4. Yangi src/umumiy/json-kerak.ts (kanon; nega kerakligi — req darsida):
// json-kerak.ts — marshrut darajasidagi middleware: tanali so'rov
// faqat JSON bo'lsin (415)
import type { RequestHandler } from "express";
import { HttpXato } from "./http-xato.ts";
// Express 5: Content-Type JSON bo'lmasa express.json() tanani
// o'qimaydi va req.body = undefined — xato YO'Q. Shuning uchun
// turini o'zimiz tekshiramiz (req.is: JSON — "application/json",
// boshqa — false, tana yo'q — null)
export const jsonKerak: RequestHandler = (req, _res, next) => {
if (req.is("application/json") !== "application/json")
throw new HttpXato(415,
"Content-Type: application/json bo'lishi kerak");
next();
};5. src/ilova.ts — to'liq yangi fayl. src/ombor.ts va src/vazifa.ts holat 07 dagidek qoladi (sinxron XotiraOmbori):
// ilova.ts — Express ilovasi (oraliq holat: marshrutlar shu
// faylda, #13 da Router va qatlamlarga bo'linadi).
// listen() YO'Q — u ishga-tushir.ts da
import express from "express";
import type { ErrorRequestHandler, RequestHandler } from "express";
import { join } from "node:path";
import { HttpXato } from "./umumiy/http-xato.ts";
import { jsonKerak } from "./umumiy/json-kerak.ts";
import { ozgarishniTekshir, yangiVazifaniTekshir } from "./vazifa.ts";
import type { XotiraOmbori } from "./ombor.ts";
export type Bogliqliklar = { ombor: XotiraOmbori };
function idniOl(xom: string): number {
if (!/^[1-9]\d{0,9}$/.test(xom)) {
throw new HttpXato(400, "id — musbat butun son");
}
return Number(xom);
}
// Express metod mos kelmasa 404 beradi — 405 + Allow ni o'zimiz
function metodYoq(allow: string): RequestHandler {
return (req, res) => {
res.set("Allow", allow);
throw new HttpXato(405, `${req.method} bu manzilda yo'q`);
};
}
function topilmadi(id: number): HttpXato {
return new HttpXato(404, `Vazifa ${String(id)} topilmadi`);
}
const xatoIshlovchi: ErrorRequestHandler = (
xato: unknown, _req, res, next,
) => {
if (res.headersSent) {
next(xato); // javob yarmida — Express o'zi ulanishni uzadi
return;
}
if (xato instanceof HttpXato) {
res.status(xato.holat).json({ xato: xato.message });
return;
}
// body-parser xatolari: `type` maydoni bilan (http-errors)
const tur =
typeof xato === "object" && xato !== null && "type" in xato
? xato.type
: undefined;
if (tur === "entity.parse.failed") {
res.status(400).json({ xato: "Tana yaroqli JSON emas" });
return;
}
if (tur === "entity.too.large") {
res.status(413).json({ xato: "Tana 16 KB dan katta" });
return;
}
// Boshqa kutubxonalar (serve-static: 416, 403...) http-errors
// tashlaydi: status + expose
if (
typeof xato === "object" && xato !== null
&& "status" in xato && typeof xato.status === "number"
&& xato.status < 500
&& "expose" in xato && xato.expose === true
&& xato instanceof Error
) {
res.status(xato.status).json({ xato: xato.message });
return;
}
console.error(xato);
res.status(500).json({ xato: "Server xatosi" });
};
export function ilovaYarat({ ombor }: Bogliqliklar): express.Express {
const app = express();
app.disable("x-powered-by"); // "Express" ekanini oshkor qilmaymiz
app.use(express.static(join(import.meta.dirname, "..", "public")));
app.use(express.json({ limit: "16kb" }));
app.route("/vazifalar")
.get((req, res) => {
const b = req.query.bajarildi;
if (b !== undefined && b !== "true" && b !== "false") {
throw new HttpXato(400, "bajarildi — true yoki false");
}
const royxat = ombor.royxat();
res.json(b === undefined
? royxat
: royxat.filter((v) => v.bajarildi === (b === "true")));
})
.post(jsonKerak, (req, res) => {
const t = yangiVazifaniTekshir(req.body);
if (!t.ok) throw new HttpXato(422, t.xato);
const v = ombor.yarat(t.qiymat);
res.status(201).location(`/vazifalar/${String(v.id)}`).json(v);
})
.all(metodYoq("GET, HEAD, POST"));
app.route("/vazifalar/:id")
.get((req, res) => {
const id = idniOl(req.params.id);
const v = ombor.ol(id);
if (!v) throw topilmadi(id);
res.json(v);
})
.patch(jsonKerak, (req, res) => {
const id = idniOl(req.params.id);
const t = ozgarishniTekshir(req.body);
if (!t.ok) throw new HttpXato(422, t.xato);
const v = ombor.yangila(id, t.qiymat);
if (!v) throw topilmadi(id);
res.json(v);
})
.delete((req, res) => {
const id = idniOl(req.params.id);
if (!ombor.ochir(id)) throw topilmadi(id);
res.sendStatus(204);
})
.all(metodYoq("GET, HEAD, PATCH, DELETE"));
app.use((req) => {
throw new HttpXato(404, `${req.method} ${req.path} topilmadi`);
});
app.use(xatoIshlovchi);
return app;
}Bu fayl — keyingi uch darsning "xaritasi": req.params, req.query, req.body, jsonKerak — req darsida; res.status().location().json(), sendStatus — res darsida; tartib, 404, xatoIshlovchi, metodYoq — middleware darsida. Hozir tuzilmaga qarang: static → JSON tana → marshrutlar → JSON 404 → xato ishlovchi. ilovaYarat da listen yo'q — testlar ilovani istalgan portda (0) ishga tushira oladi.
Express app.use va app.route larni yozilgan tartibda sinaydi. PATCH /vazifalar/7 so'rovi {"bajarildi":true} tanasi bilan shu yo'ldan o'tadi:
| Qadam | Middleware | Natija |
|---|---|---|
| 1 | express.static |
faqat GET/HEAD ga fayl beradi; PATCH — next() |
| 2 | express.json |
tana o'qildi: req.body = { bajarildi: true } |
| 3 | /vazifalar marshruti |
yo'l mos emas — o'tkazib yuboriladi |
| 4 | /vazifalar/:id → jsonKerak |
Content-Type JSON — next() |
| 5 | .patch ishlovchisi |
vazifa topildi — res.json(v), 200; zanjir shu yerda tugaydi |
Agar 5-qadamda vazifa topilmasa, ishlovchi throw qiladi. Express qolgan oddiy ishlovchilarni (.all, JSON 404) tashlab, to'g'ridan oxirgi xatoIshlovchi ga o'tadi — u 404 JSON qaytaradi. JSON 404 ishlovchisiga esa faqat hech bir marshrut mos kelmagan so'rov yetadi.
6. src/ishga-tushir.ts — createServer ga endi Express ilovasi beriladi. Timeout'lar holat 07 dagidek. Kanon holat 13 fayli (bugun bitta farq bilan: XotiraOmbori hali ./ombor.ts dan):
// ishga-tushir.ts — http server (Express ilovasi ishlovchi
// sifatida), timeout'lar va tinglash
import { createServer } from "node:http";
import type { Server } from "node:http";
import type { AddressInfo } from "node:net";
import { ilovaYarat } from "./ilova.ts";
import type { Bogliqliklar } from "./ilova.ts";
import { XotiraOmbori } from "./ombor.ts";
export type Ishlayotgan = { server: Server; manzil: string };
type Sozlama = { port?: number; host?: string;
bogliqliklar?: Bogliqliklar };
export async function ishgaTushir({
port = 0, host = "127.0.0.1",
bogliqliklar = { ombor: new XotiraOmbori() },
}: Sozlama = {}): Promise<Ishlayotgan> {
// app.listen() ham shuni qiladi; createServer — timeout'larni
// berish va server obyektini olish uchun
const server = createServer(
{
// LB (nginx, ALB) bo'sh ulanishni ~60 s ushlaydi — Node undan
// KEYIN yopsin
keepAliveTimeout: 65_000,
// Slowloris: sarlavhalar 10 s ichida kelmasa — 408
headersTimeout: 10_000,
requestTimeout: 30_000,
},
ilovaYarat(bogliqliklar),
);
await new Promise<void>((resolve, reject) => {
server.once("error", reject); // EADDRINUSE va h.k.
server.listen(port, host, () => {
server.off("error", reject);
resolve();
});
});
const { port: haqiqiy } = server.address() as AddressInfo;
return { server, manzil: `http://${host}:${String(haqiqiy)}` };
}(Qatorlar telefon uchun bo'lingan, kod ma'nosi aynan.) app.listen() emas, createServer — timeout'larni berish va server obyektini yop() ga uzatish uchun.
7. Testlar. Ikki o'zgarish. (1) test/api.test.ts da allow endi "GET, HEAD, POST" — Express HEAD ni o'zi qo'llaydi. (2) Static fayl testi fetch bilan 304 olmaydi — fetch ETag'li so'rovga o'zi Cache-Control: no-cache qo'shadi va Express 200 beradi (sababi req darsida). Shartli so'rovlar uchun test/yordamchi.ts ga node:http bilan so'rov yuboradigan yordamchi qo'shamiz (kanon):
import { request } from "node:http";
import type { IncomingHttpHeaders } from "node:http";
export type XomJavob = { holat: number;
sarlavhalar: IncomingHttpHeaders; tana: string };
/**
* node:http bilan so'rov. Nega fetch emas: fetch (undici)
* If-None-Match bor so'rovga o'zi `Cache-Control: no-cache` +
* `Pragma: no-cache` qo'shadi (Fetch standarti) — Express (fresh)
* esa no-cache'li so'rovga 304 bermaydi.
*/
export function xomSorov(url: string, { metod = "GET",
sarlavhalar = {}, tana }: { metod?: string;
sarlavhalar?: Record<string, string>; tana?: string } = {},
): Promise<XomJavob> {
return new Promise((resolve, reject) => {
const so = request(url, { method: metod, headers: sarlavhalar },
(res) => {
let b = "";
res.setEncoding("utf8");
res.on("data", (d: string) => (b += d));
res.on("end", () => {
resolve({ holat: res.statusCode ?? 0,
sarlavhalar: res.headers, tana: b });
});
});
so.on("error", reject);
so.end(tana);
});
}Static test esa shunday bo'ladi (kanon):
test("statik (express.static): index.html, ETag → 304, "
+ "Range → 206, traversal → 404", async () => {
const r = await xomSorov(`${asos}/`);
assert.equal(r.holat, 200);
assert.match(String(r.sarlavhalar["content-type"]), /text\/html/);
const etag = String(r.sarlavhalar.etag);
assert.equal((await xomSorov(`${asos}/`,
{ sarlavhalar: { "If-None-Match": etag } })).holat, 304);
const q = await xomSorov(`${asos}/index.html`,
{ sarlavhalar: { Range: "bytes=0-14" } });
assert.equal(q.holat, 206);
assert.equal(q.tana, "<!doctype html>");
assert.equal((await xomSorov(`${asos}/index.html`,
{ sarlavhalar: { Range: "bytes=99999-" } })).holat, 416);
// node:http yo'lni normallashtirmaydi — server o'zi
// himoyalanishi kerak
assert.equal(
(await xomSorov(`${asos}/../package.json`)).holat, 404);
assert.equal(
(await xomSorov(`${asos}/..%2fpackage.json`)).holat, 404);
});npm run check — tip 0, lint 0, testlar 7/7. Bu — eng yaxshi isbot: holat 07 dagi API shartnomasi (statuslar, JSON shakli) Express'da ham buzilmadi.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
SyntaxError: Cannot use import statement outside a module |
package.json da "type": "module" yo'q |
qo'shing yoki .mjs |
Cannot find module 'express' |
o'rnatilmagan | npm i express |
PUT ga 404 HTML, 405 emas |
Express 405 bermaydi | .all() + Allow (middleware darsi) |
Javobda X-Powered-By: Express |
sukut | app.disable("x-powered-by") |
Internetdagi misol ishlamaydi (/*) |
Express 4 sintaksisi | Express 5 shakli (Express 5 darsi) |
app.listen timeout'larni bermaydi |
Express sozlamasi emas | createServer(sozlama, app) |
Cannot find module 'express' imported from … — "express moduli topilmadi". node_modules yo'q yoki boshqa papkada ishga tushirdingiz.
8. Mashqlar
Yechimlar kurs/mashqlar/25/09-express-kirish/ da.
1-mashq (oson): to'ldiring
express()qaytaradigan qiymat turi —- Express 5 talab qiladigan eng past Node versiyasi —
X-Powered-Byni o'chirish —app.("x-powered-by")- Marshrut yo'q metodga Express qaytaradigan status —
app.listenqaytaradigan obyekt —http.
Yechim
- function —
(req, res, next),createServerga beriladi. - 18 —
"engines": { "node": ">= 18" }. - disable —
app.set("x-powered-by", false)ham bir xil. - 404 — 405 ni o'zingiz qo'yasiz.
- Server — timeout'lar va
close()shu obyektda.
2-mashq (o'rta): o'z "kichik Express"ingiz
Express — yupqa qatlam ekanini isbotlang. kichikIlova() funksiyasini faqat node:http bilan yozing: u funksiya qaytarsin (ishlovchi), unda get(yol, fn) va post(yol, fn) metodlari va listen(...) bo'lsin. Har so'rovda res.json(qiymat) yordamchisi qo'shilsin. Marshrut topilmasa — 404 va Cannot <METOD> <yol>. Eslatma: funksiya ham obyekt, unga xususiyat qo'shish mumkin (funksiya obyekt sifatida).
Yechim
import { createServer } from "node:http";
function kichikIlova() {
const yollar = [];
const ilova = (req, res) => {
const yol = new URL(req.url, "http://x").pathname;
const mos = yollar.find(
(y) => y.metod === req.method && y.yol === yol);
res.json = (qiymat) => {
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify(qiymat));
};
if (!mos) {
res.statusCode = 404;
return res.end(`Cannot ${req.method} ${yol}`);
}
mos.ishlovchi(req, res);
};
for (const metod of ["GET", "POST"]) {
ilova[metod.toLowerCase()] = (yol, ishlovchi) =>
yollar.push({ metod, yol, ishlovchi });
}
ilova.listen = (...args) => createServer(ilova).listen(...args);
return ilova;
}
const app = kichikIlova();
app.get("/salom", (req, res) => res.json({ xabar: "salom" }));
const server = app.listen(0, "127.0.0.1");
await new Promise((ok) => server.once("listening", ok));
const a = `http://127.0.0.1:${server.address().port}`;
const r1 = await fetch(`${a}/salom`);
const tur = r1.headers.get("content-type");
console.log(r1.status, tur, await r1.text());
const r2 = await fetch(`${a}/salom`, { method: "PUT" });
console.log(r2.status, await r2.text());
server.closeAllConnections();
server.close();Konsolda:
200 application/json {"xabar":"salom"}
404 Cannot PUT /salom30 qatorda Express'ning asosiy g'oyasi: ilova — funksiya, marshrutlar — ro'yxat, res ga yordamchi metodlar qo'shiladi. Haqiqiy Express bunga middleware zanjiri, yo'l parametrlari va xato ishlashni qo'shadi.
3-mashq (qiyin): 405 bilan Express
Express 5.3.0 bilan «Bahor» oshxonasi uchun /taomlar yozing: GET — ro'yxat, POST — JSON tanadan yangi taom (201). Boshqa metodlar — 405, Allow: GET, HEAD, POST va JSON xabar. X-Powered-By bo'lmasin. Eslatma: app.route("/taomlar").get(…).post(…).all(…) — bitta yo'lga bir nechta metod; .all — qolgan hamma metod; express.json() — JSON tanani req.body ga o'qiydi (tafsiloti req darsida). npm i express@5.3.0 dan keyin ishga tushiring.
Yechim
import express from "express";
const taomlar = [{ nom: "osh", narx: 35000 }];
const app = express();
app.disable("x-powered-by");
app.use(express.json());
app.route("/taomlar")
.get((req, res) => res.json(taomlar))
.post((req, res) => {
taomlar.push(req.body);
res.status(201).json(req.body);
})
.all((req, res) => {
res.set("Allow", "GET, HEAD, POST");
res.status(405).json({ xato: `${req.method} mumkin emas` });
});
const server = app.listen(0, "127.0.0.1");
await new Promise((ok) => server.once("listening", ok));
const url = `http://127.0.0.1:${server.address().port}/taomlar`;
const yangi = { nom: "manti", narx: 30000 };
const r1 = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(yangi),
});
console.log(r1.status, await r1.text());
const r2 = await fetch(url);
console.log(r2.status, await r2.text());
const r3 = await fetch(url, { method: "DELETE" });
console.log(r3.status, r3.headers.get("allow"), await r3.text());
console.log("x-powered-by:", r3.headers.get("x-powered-by"));
server.closeAllConnections();
server.close();Konsolda:
201 {"nom":"manti","narx":30000}
200 [{"nom":"osh","narx":35000},{"nom":"manti","narx":30000}]
405 GET, HEAD, POST {"xato":"DELETE mumkin emas"}
x-powered-by: null.all() zanjirning oxirida — GET va POST undan oldin ushlanadi, unga faqat qolganlari yetadi. Tartibni almashtirsangiz, hamma so'rov 405 oladi. Validatsiya yo'q (req.body tekshirilmaydi) — bu validatsiya darsida.
4-mashq: API qadami
«API qadami» bo'limidagi 1–7 qadamlarni bajaring. Avval testlarni o'zgartirmasdan npm test qiling — qaysi test yiqilishini va nega ekanini yozib qo'ying. Keyin 7-qadam (xomSorov, Allow) bilan tuzating: npm run check — 7/7. Commit qilmang.
Yechim
To'liq fayllar — «API qadami» bo'limida. Testlarni o'zgartirmasdan ikki tekshiruv yiqiladi: allow — "GET, HEAD, POST" keldi ("GET, POST" kutilgan edi), static testida fetch + If-None-Match 304 o'rniga 200 oldi. Ikkinchisining sababi — undici bunday so'rovga Cache-Control: no-cache qo'shadi (req darsi).
9. Real ishda
- Express — Node backend'larining katta qismida; NestJS ham sukut bo'yicha ichida Express ishlatadi. Vakansiyalarda "Node.js/Express" juftligi juda ko'p uchraydi.
- Eski loyihalar — ko'pchiligi hali Express 4 da. 4 → 5 ko'chish — real ish vazifasi (Express 5 darsi).
- Arxitektura odati: ilovani yaratish (
ilovaYarat) va tinglash (listen) alohida — testlar, serverless platformalar va graceful shutdown uchun. - Intervyu: "Express nima,
httpdan farqi?", "app.listenichida nima bor?", "Express 5 da nima o'zgardi?".
Xulosa
- Express —
node:httpustidagi yupqa qatlam: routing + middleware;app—(req, res, next)funksiyasi. app.listen()=http.createServer(app).listen(); timeout'lar vaclose()—http.Serverda.- Express 5.3.0, Node 18+, ESM; eski maqolalar ko'pincha Express 4 uchun.
- Sukut:
X-Powered-By(o'chiring), har javobga ETag, HTML 404, avtomatikHEAD, 405 YO'Q. - Narxi: 65 paket, +118 ms sovuq start, kichik javobda 27 096 → 9 724 req/s; katta javobda farq yo'qoladi.
Keyingi dars: req obyekti — params, query (Express 5 getter), body, req.is(), req.ip va express.json() ning jim tuzog'i.
Manbalar
- Express hujjati — "Hello world", API 5.x, "Migrating to Express 5": https://expressjs.com/en/guide/migrating-5.html (2026-10-24 da ochildi)
- Express blogi — "Express@5.1.0: Now the Default on npm with LTS Timeline" (2025-03-31; 5.0.0 — 2024-09-09): https://expressjs.com/en/blog/2025-03-31-v5-1-latest-release (2026-10-24 da ochildi)
- npm — express 5.3.0 (2026-10-09), @types/express 5.0.6: https://www.npmjs.com/package/express
- Kanon:
vazifalar-apiholat 07 va 13 o'lchovlari (sovuq start, autocannon),ilova.ts,ishga-tushir.ts.typeof app, birinchi server sarlavhalari,npm ichiqishi — biz ishga tushirdik (Node 24.21.0, npm 11.19.0, Windows 11).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!