Mundarija (36)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. http modul nima qiladi
- 2.2. createServer va request handler
- 2.3. req — IncomingMessage (Readable stream — 5.4)
- 2.4. res — ServerResponse (Writable stream — 5.4)
- 2.5. Status kodlar va headerlar (0.4 amaliyoti)
- 2.6. Routing — qo'lda (req.url + req.method)
- 2.7. Query parametrlarni parse qilish (0.4: URL)
- 2.8. Request body'ni o'qish (POST — stream! — 5.4)
- 2.9. JSON javob qaytarish (API uchun)
- 2.10. Static fayl xizmati (stream bilan — 5.4)
- 2.11. http.request — client sifatida (so'rov yuborish)
- 2.12. HTTP vs HTTPS (shifrlangan ulanish — 0.4)
- 2.13. Nega Express? (http'ning kamchiliklari)
- 2.14. Production Server Nozikliklari: Keep-Alive Timeouts, Slowloris va True Graceful Shutdown
- 3. Sintaksis — tez ma'lumotnoma
- 4. Batafsil kod namunalari
- Misol 1 — Eng oddiy server (2.1)
- Misol 2 — Qo'lda routing (2.6)
- Misol 3 — Query parametrlar (2.7)
- Misol 4 — POST body o'qish (stream — 2.8, 5.4)
- Misol 5 — Mini REST API (CRUD — 0.4, 6 ga ko'prik)
- Misol 6 — Static fayl + HTML (2.10, 5.4)
- Misol 7 — Graceful shutdown (server'ni to'g'ri to'xtatish)
- 5. To'g'ri va noto'g'ri holatlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- 8. Eng yaxshi amaliyotlar (best practices)
- 9. Amaliy loyiha: "Sof Node bilan REST API (Express'siz)"
- Maqsad
- Talablar (requirements)
- Maslahatlar (hint)
- "Tayyor" mezonlari (acceptance criteria)
- 10. Xulosa va keyingi bobga ko'prik
- Foydalanilgan rasmiy/ishonchli manbalar
Node.js http moduli — Express'siz server yaratish (5.5-bob)
5-QISM — Node.js Backend · 5-mavzu
1. Kirish va motivatsiya
0.4-bobda HTTP nazariyasini (client-server, so'rov/javob, status kodlar, metodlar) o'rgandik. 5.1–5.4-boblarda Node mexanizmlarini (event loop, core modullar, stream/event) ko'rdik. Endi hammasini birlashtiramiz: faqat core http modul bilan, Express'siz, o'z qo'limiz bilan server yaratamiz.
"Nega Express'siz? Hamma Express ishlatadi-ku!" — to'g'ri, real loyihada Express 5.6-bob yoki NestJS (8) ishlatasiz. Lekin Express — http modulning o'rami (wrapper). Express "sehrini" tushunish uchun, pardaning ortida nima borligini bilish kerak: so'rov qanday keladi, javob qanday yuboriladi, routing qanday ishlaydi, body qanday o'qiladi. Bu bobni o'tgandan keyin Express sizga "sehr" emas, "qulaylik" bo'lib ko'rinadi.
http modul — Node'ning eng muhim core moduli 5.3-bob: u TCP server yaratadi, HTTP protokolini 0.4-bob parse qiladi va sizga req/res obyektlarini beradi. Va eng muhimi: req — Readable stream, res — Writable stream 5.4-bob! Ya'ni 5.4-bob bevosita shu yerda ishlaydi.
O'xshatish:
httpmodul — restoranni noldan qurish: o'zingiz eshik ochasiz, mehmonni kutib olasiz, buyurtmani yozib olasiz, taom tayyorlaysiz, olib chiqasiz. Express 5.6-bob — tayyor restoran tizimi (ofitsiantlar, oshxona tartibi). Avval noldan qurishni bilsangiz, tayyor tizimni ham chuqur tushunasiz.
Nega muhim?
- Express/NestJS poydevori — ular
httpustiga qurilgan; ichini bilish — chuqur tushunish. - HTTP'ni amalda — 0.4 nazariyasi kodga aylanadi (so'rov/javob/status/header).
- Stream/event (5.4) —
req/resaynan shular. - Routing, body parsing, status — Express'da avtomatik bo'lgan narsalar ichini ko'rasiz.
2. Nazariya — chuqur tushuntirish
2.1. http modul nima qiladi
http (5.3: core modul) — createServer bilan TCP server yaratadi (0.4: TCP/port). U pardaning ortida (nodejs.org):
- Belgilangan portni tinglaydi (0.2: port, 0.4).
- Ulanish kelganda HTTP protokolini (0.4) parse qiladi (matn → obyekt).
- Har so'rov uchun
requesteventini chiqaradi (5.4: EventEmitter), sizgareq/resberadi.
import http from "node:http";
const server = http.createServer((req, res) => {
// Bu funksiya HAR so'rovda chaqiriladi (5.4: event handler)
res.end("Salom, dunyo!");
});
server.listen(3000, () => {
console.log("Server http://localhost:3000 da"); // (0.4: localhost, port)
});2.2. createServer va request handler
createServer(handler) — handler har so'rovda chaqiriladi (5.1: event loop'da; bitta thread minglab so'rovni — 5.1):
Brauzer/client → so'rov 0.4-bob → Node http parse → handler(req, res)
↓
Brauzer ← javob 0.4-bob ←──────────────── res.end(...)
createServeraslida EventEmitter 5.4-bob:http.createServer(handler)—server.on("request", handler)ning qisqasi. Server — EventEmitter; "request" — event.
2.3. req — IncomingMessage (Readable stream — 5.4)
req — http.IncomingMessage (Readable stream — 5.4): kiruvchi so'rov ma'lumotini saqlaydi 0.4-bob:
req.method // "GET" / "POST" / ... (0.4: metod)
req.url // "/users?page=2" (path + query — 0.4: URL)
req.headers // { host, "content-type", authorization, ... } (0.4: header)
req.httpVersion // "1.1"
// req — Readable stream → body uchun "data"/"end" eventlari (2.5, 5.4)
req.url— faqat path+query (host'siz):/users?page=20.4-bob. To'liq URL emas. Query (?page=2) ni ajratish uchun parse kerak 2.7-bob.
2.4. res — ServerResponse (Writable stream — 5.4)
res — http.ServerResponse (Writable stream — 5.4): javobni yuboradi 0.4-bob:
res.writeHead(200, { "Content-Type": "application/json" }); // status + header (0.4)
res.statusCode = 200; // status alohida (0.4)
res.setHeader("X-Custom", "qiymat"); // header alohida
res.write("qism"); // body qismi (stream — 5.4)
res.end("oxirgi qism"); // YAKUNLASH (majburiy! 5.4)
res.end()MAJBURIY — har javobni yakunlash kerak (nodejs.org, 5.4: Writable).endchaqirilmasa — brauzer kutib qoladi (so'rov "osilib" qoladi). VawriteHeadwrite/end'dan oldin chaqirilishi kerak.
2.5. Status kodlar va headerlar (0.4 amaliyoti)
0.4-bobdagi status kodlar (2xx/4xx/5xx) endi kodda:
res.writeHead(200, {...}); // OK
res.writeHead(201, {...}); // Created (POST muvaffaqiyatli — 0.4)
res.writeHead(404, {...}); // Not Found (0.4)
res.writeHead(400, {...}); // Bad Request (0.4)
res.writeHead(500, {...}); // Internal Server Error (0.4)Muhim headerlar: Content-Type (javob turi — application/json, text/html), Content-Length, Cache-Control, CORS 5.20-bob.
Connection: keep-alive0.4-bob: HTTP/1.1'da ulanish qayta ishlatiladi — bitta TCP ulanish ustida ketma-ket bir nechta so'rov ketadi (har so'rovga yangi ulanish ochilmaydi → tezroq). Node'ninghttpserveri buni avtomatik qiladi; siz alohida sozlamaysiz.req.headers.connectionorqali ko'rishingiz mumkin. Mijoz tomonida (http.request) ko'p so'rov yuborsangiz, ulanishni qayta ishlatish uchunhttp.Agent({ keepAlive: true })ishlatiladi.
2.6. Routing — qo'lda (req.url + req.method)
Express'da app.get("/users", ...) avtomatik; http'da qo'lda req.url va req.methodni tekshirasiz (nodejs.org):
const server = http.createServer((req, res) => {
if (req.method === "GET" && req.url === "/") {
res.writeHead(200).end("Bosh sahifa");
} else if (req.method === "GET" && req.url === "/users") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify([{ id: 1, ism: "Ali" }])); // (2.8: JSON)
} else {
res.writeHead(404).end("Topilmadi"); // (0.4: 404)
}
});Bu — Express routerning "ichi". Ko'p route bo'lsa, bu
if/elsezanjiri chalkashadi — aynan shuning uchun Express 5.6-bob keladi.
2.7. Query parametrlarni parse qilish (0.4: URL)
req.url — /users?page=2&limit=10; query'ni ajratish uchun URL (5.3, 2.17):
const url = new URL(req.url, `http://${req.headers.host}`); // to'liq URL (5.3)
url.pathname; // "/users" (query'siz)
url.searchParams.get("page"); // "2" (0.4: query)
url.searchParams.get("limit"); // "10"2.8. Request body'ni o'qish (POST — stream! — 5.4)
Eng muhim qism: req — Readable stream (2.3, 5.4). POST body bo'lak-bo'lak (chunk) keladi; uni data/end eventlari bilan yig'amiz 5.4-bob:
function bodyOqi(req) {
return new Promise((resolve, reject) => { // (2.11: Promise)
let body = "";
req.on("data", (chunk) => { body += chunk; }); // chunk yig'ish (5.4)
req.on("end", () => resolve(body)); // tugadi (5.4)
req.on("error", reject); // xato (5.4: error!)
});
}
// Ishlatish (POST'da)
const xom = await bodyOqi(req);
const data = JSON.parse(xom); // matn → obyekt (2.8)Body avtomatik kelmaydi!
req.body—http'da yo'q (Express'daexpress.json()middleware qo'shadi — 5.6). Sofhttp'da body'ni qo'lda, stream chunk'larini yig'ib o'qiysiz 5.4-bob. Bu — Express body-parser'ning "ichi".
2.9. JSON javob qaytarish (API uchun)
function jsonJavob(res, status, data) {
res.writeHead(status, { "Content-Type": "application/json" }); // (2.5)
res.end(JSON.stringify(data)); // obyekt → matn (2.8)
}
jsonJavob(res, 200, { ism: "Ali" });
jsonJavob(res, 404, { xato: "Topilmadi" });2.10. Static fayl xizmati (stream bilan — 5.4)
HTML/CSS/rasm faylni yuborish — stream bilan (5.4: xotira-samarali):
import { createReadStream } from "node:fs";
import path from "node:path";
if (req.url === "/index.html") {
res.writeHead(200, { "Content-Type": "text/html" });
createReadStream(path.join(import.meta.dirname, "index.html")).pipe(res); // (5.4)
}2.11. http.request — client sifatida (so'rov yuborish)
http faqat server emas — client ham (boshqa API'ga so'rov — 5.18: SMS). Lekin zamonaviy kodda fetch (2.17, Node'da bor) yoki Axios 2.18-bob qulayroq:
// Zamonaviy: Node'da fetch (2.17)
const res = await fetch("https://api.example.com/data");
const data = await res.json();
// http.request — past darajali, kamdan-kam to'g'ridan ishlatiladi2.12. HTTP vs HTTPS (shifrlangan ulanish — 0.4)
http modul — shifrlanmagan ulanish (0.4: ma'lumot ochiq matnda ketadi). Productionda (10) har doim HTTPS kerak: u TLS sertifikat bilan ulanishni shifrlaydi (parol/token o'rtada ushlab olinmaydi). Node'da https core modul bor — interfeysi http bilan bir xil, faqat sertifikat (key/cert) qo'shiladi:
import https from "node:https";
import { readFileSync } from "node:fs";
const ssl = {
key: readFileSync("private-key.pem"), // maxfiy kalit
cert: readFileSync("certificate.pem"), // sertifikat
};
https.createServer(ssl, (req, res) => { // qolgani http bilan AYNAN bir xil
res.end("Xavfsiz (TLS) ulanish");
}).listen(443); // HTTPS standart porti — 443 (0.4)Amalda sertifikatni to'g'ridan kodda boshqarmaysiz: HTTPS'ni odatda reverse proxy (Nginx) yoki bulut platformasi (10) hal qiladi — Node serveringiz oddiy
http'da qoladi, TLS esa undan oldinda "tugaydi" (TLS termination). Bepul sertifikat uchun — Let's Encrypt.
2.13. Nega Express? (http'ning kamchiliklari)
Sof http bilan ishlaganda quyidagilarni qo'lda qilasiz (zerikarli, xatoga moyil):
- Routing —
if/elsezanjiri 2.6-bob — ko'p route'da chalkash. - Body parsing — har safar stream o'qish 2.8-bob.
- Query/params — qo'lda parse 2.7-bob.
- Middleware yo'q — umumiy logika (auth, log) takrorlanadi.
- Status/header — qo'lda.
Express (5.6) — bularning hammasini avtomatlashtiradi: app.get("/users/:id", ...), req.body, req.params, middleware. Lekin u http ustiga qurilgan — shuning uchun ichini bilish muhim.
2.14. Production Server Nozikliklari: Keep-Alive Timeouts, Slowloris va True Graceful Shutdown
1. Nginx / AWS ALB bilan Keep-Alive Race Condition (502 Bad Gateway tuzog'i)
Agar Node.js serveringiz Nginx yoki AWS ALB (Application Load Balancer) orqasida ishlayotgan bo'lsa, Node.js serveringizning keepAliveTimeout qiymati yuklama muvozanatlovchi (Load Balancer) ning timeout qiymatidan KATTA bo'lishi shart!
Muammo: Nginx (timeout 65s) Node.js (default keepAliveTimeout 5s)
Nginx TCP ulanishni ochiq deb hisoblab yangi so'rov yuboradi,
lekin Node.js ayni shu millisekundda ulanishni yopadi (FIN yuboradi).
Natija mijozga: 502 Bad Gateway (Connection reset by peer)!Production sozlamasi:
const server = http.createServer(handler);
// Agar Nginx keepalive_timeout 65s bo'lsa:
server.keepAliveTimeout = 66000; // 66 sekund (Nginx'dan katta bo'lishi shart!)
server.headersTimeout = 67000; // keepAliveTimeout'dan doim 1-2 soniya katta bo'lishi kerak2. Slowloris DoS hujumi va Server Timeouts
Hujumchi serverga ulanish ochib, HTTP sarlavhalarini soniyasiga 1 baytdan juda sekin yuboradi. Barcha socketlar band bo'lib, haqiqiy foydalanuvchilar kira olmay qoladi. Node.js buni oldini olish uchun taymerlar beradi:
server.requestTimeout = 30000; // Butun so'rov maksimal 30s ichida yakunlanishi shart
server.headersTimeout = 10000; // Sarlavhalar 10s ichida to'liq kelishi shart3. Mukammal Graceful Shutdown (Haqiqiy toza to'xtatish)
Klassik server.close() chaqirilganda, ochiq bo'lgan keep-alive ulanishlar yopilmagani sababli jarayon uzoq vaqt "osilib" qolishi mumkin.
Node 18.2+ versiyasidan boshlab maxsus yechim kiritilgan:
function gracefulShutdown() {
console.log("SIGTERM qabul qilindi. Server to'xtatilmoqda...");
// 1. Yangi ulanishlarni qabul qilishni to'xtatish
server.close((err) => {
if (err) {
console.error("Yopilishda xato:", err);
process.exit(1);
}
console.log("Barcha faol so'rovlar yakunlandi. Chiqilmoqda.");
process.exit(0);
});
// 2. Yangi bo'sh turgan (idle) keep-alive ulanishlarni zudlik bilan yopish
if (typeof server.closeIdleConnections === "function") {
server.closeIdleConnections();
}
// 3. Agar 10 sekund ichida faol so'rovlar tugamasa, majburiy to'xtatish (Force Exit)
setTimeout(() => {
console.error("Majburiy to'xtatish (Timeout)!");
process.exit(1);
}, 10000).unref(); // unref() Event Loopni ushlab turmaydi
}
process.on("SIGTERM", gracefulShutdown);
process.on("SIGINT", gracefulShutdown);3. Sintaksis — tez ma'lumotnoma
import http from "node:http";
const server = http.createServer((req, res) => {
// req (Readable — 5.4): req.method, req.url, req.headers
// res (Writable — 5.4): res.writeHead(status, headers), res.write(), res.end()
});
server.listen(3000, cb);
// Query (5.3)
const url = new URL(req.url, `http://${req.headers.host}`);
url.pathname; url.searchParams.get("x");
// Body (stream — 5.4, 2.8)
req.on("data", c => body += c); req.on("end", () => JSON.parse(body));
// JSON javob
res.writeHead(200, {"Content-Type":"application/json"});
res.end(JSON.stringify(data));4. Batafsil kod namunalari
Misol 1 — Eng oddiy server (2.1)
import http from "node:http";
const server = http.createServer((req, res) => {
console.log(`${req.method} ${req.url}`); // har so'rovni loglang (0.4)
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
res.end("Salom, backend dunyosi!"); // (2.4: end majburiy)
});
server.listen(3000, () => {
console.log("Server http://localhost:3000 da ishlayapti");
});
// node server.js → brauzerda localhost:3000Misol 2 — Qo'lda routing (2.6)
import http from "node:http";
const server = http.createServer((req, res) => {
res.setHeader("Content-Type", "application/json; charset=utf-8");
// Routing — req.method + req.url (2.6)
if (req.method === "GET" && req.url === "/") {
res.writeHead(200).end(JSON.stringify({ xabar: "Bosh sahifa" }));
} else if (req.method === "GET" && req.url === "/health") {
res.writeHead(200).end(JSON.stringify({ holat: "ok", vaqt: Date.now() }));
} else {
res.writeHead(404).end(JSON.stringify({ xato: "Sahifa topilmadi" })); // (0.4: 404)
}
});
server.listen(3000);Misol 3 — Query parametrlar (2.7)
const server = http.createServer((req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`); // (5.3, 2.7)
if (url.pathname === "/qidiruv") {
const q = url.searchParams.get("q") ?? ""; // ?q=telefon (0.4)
const sahifa = Number(url.searchParams.get("page") ?? 1); // (2.6: Number)
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ qidiruv: q, sahifa }));
} else {
res.writeHead(404).end("Topilmadi");
}
});
// localhost:3000/qidiruv?q=telefon&page=2 → {"qidiruv":"telefon","sahifa":2}Misol 4 — POST body o'qish (stream — 2.8, 5.4)
import http from "node:http";
// Body'ni stream chunk'laridan yig'ish (5.4)
function bodyOqi(req) {
return new Promise((resolve, reject) => {
let body = "";
req.on("data", (chunk) => {
body += chunk;
if (body.length > 1e6) { // 1MB chegara (DoS himoyasi — 14)
reject(new Error("Body juda katta"));
req.destroy();
}
});
req.on("end", () => resolve(body));
req.on("error", reject); // (5.4: error)
});
}
const server = http.createServer(async (req, res) => {
if (req.method === "POST" && req.url === "/users") {
try {
const xom = await bodyOqi(req); // body yig'ish (2.8)
const user = JSON.parse(xom); // matn → obyekt (2.8)
// ... validatsiya, DB ... (5.9, 6)
res.writeHead(201, { "Content-Type": "application/json" }); // 201 Created (0.4)
res.end(JSON.stringify({ id: 1, ...user }));
} catch (err) {
res.writeHead(400, { "Content-Type": "application/json" }); // 400 (0.4)
res.end(JSON.stringify({ xato: "Noto'g'ri JSON" })); // (2.13)
}
} else {
res.writeHead(404).end();
}
});
server.listen(3000);Misol 5 — Mini REST API (CRUD — 0.4, 6 ga ko'prik)
import http from "node:http";
let users = [{ id: 1, ism: "Ali" }]; // xotirada (keyin DB — 6)
let keyingiId = 2;
const bodyOqi = (req) => new Promise((res) => {
let b = ""; req.on("data", c => b += c); req.on("end", () => res(b));
});
const server = http.createServer(async (req, res) => {
res.setHeader("Content-Type", "application/json");
const url = new URL(req.url, `http://${req.headers.host}`);
const segments = url.pathname.split("/").filter(Boolean); // ["users","1"]
// GET /users — ro'yxat (0.4: GET)
if (req.method === "GET" && url.pathname === "/users") {
res.writeHead(200).end(JSON.stringify(users));
}
// GET /users/:id — bitta (2.7)
else if (req.method === "GET" && segments[0] === "users" && segments[1]) {
const user = users.find(u => u.id === Number(segments[1])); // (2.7: find)
if (user) res.writeHead(200).end(JSON.stringify(user));
else res.writeHead(404).end(JSON.stringify({ xato: "Topilmadi" }));
}
// POST /users — yaratish (0.4: POST → 201)
else if (req.method === "POST" && url.pathname === "/users") {
const yangi = { id: keyingiId++, ...JSON.parse(await bodyOqi(req)) };
users.push(yangi);
res.writeHead(201).end(JSON.stringify(yangi));
}
// DELETE /users/:id (0.4: DELETE)
else if (req.method === "DELETE" && segments[0] === "users") {
users = users.filter(u => u.id !== Number(segments[1])); // (2.7)
res.writeHead(204).end(); // 204 No Content (0.4)
}
else res.writeHead(404).end(JSON.stringify({ xato: "Yo'l topilmadi" }));
});
server.listen(3000, () => console.log("API: localhost:3000/users"));Misol 6 — Static fayl + HTML (2.10, 5.4)
import http from "node:http";
import { createReadStream } from "node:fs";
import path from "node:path";
const MIME = { ".html": "text/html", ".css": "text/css", ".js": "text/javascript" };
const server = http.createServer((req, res) => {
const fayl = req.url === "/" ? "/index.html" : req.url;
const yol = path.join(import.meta.dirname, "public", fayl); // (5.3)
const tur = MIME[path.extname(fayl)] ?? "application/octet-stream";
const stream = createReadStream(yol);
stream.on("error", () => { // fayl yo'q (5.4: error)
res.writeHead(404).end("Fayl topilmadi");
});
stream.once("open", () => { // fayl bor (5.4: once)
res.writeHead(200, { "Content-Type": tur });
stream.pipe(res); // stream bilan yuborish (5.4)
});
});
server.listen(3000);Misol 7 — Graceful shutdown (server'ni to'g'ri to'xtatish)
const server = http.createServer((req, res) => res.end("ok"));
server.listen(3000);
// Process to'xtatilganda (Ctrl+C / deploy) — yangi so'rovni qabul qilmay, joriylarni tugat
process.on("SIGTERM", () => { // (5.1: process events, 0.3: signal)
console.log("Server yopilmoqda...");
server.close(() => { // joriy so'rovlarni tugatib yopadi
console.log("Server toza yopildi");
process.exit(0); // (5.1)
});
});
// Production'da muhim (10): deploy paytida so'rovlar yo'qolmaydi5. To'g'ri va noto'g'ri holatlar
1) res.end()ni unutish
// ❌ javob yakunlanmadi → brauzer kutib qoladi (so'rov osiladi — 2.4)
res.write("salom");
// ✅ end bilan yakunlang
res.end("salom");2) req.bodyni to'g'ridan kutish
// ❌ http'da req.body YO'Q (Express'da bor — 2.8)
const data = req.body; // undefined
// ✅ stream'dan qo'lda o'qing (5.4)
const data = JSON.parse(await bodyOqi(req));3) writeHeadni write/enddan keyin
// ❌ header body'dan keyin yuborib bo'lmaydi (2.4)
res.end("salom");
res.writeHead(200); // ERR_STREAM_WRITE_AFTER_END
// ✅ writeHead birinchi
res.writeHead(200);
res.end("salom");4) JSON javobda Content-Type'siz
// ❌ brauzer matn deb o'ylaydi (0.4)
res.end(JSON.stringify(data));
// ✅ Content-Type bering
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(data));5) Body o'lchamini cheklamaslik (DoS — 14)
// ❌ cheksiz body → xotira to'ladi (hujum — 14)
req.on("data", c => body += c);
// ✅ chegara qo'ying (Misol 4)
if (body.length > 1e6) { req.destroy(); }6. Keng tarqalgan xatolar va yechimlari
Xato 1 — EADDRINUSE: address already in use :::3000
Sababi: port band (0.2, 0.4, 5.1). Yechimi: boshqa port; band process'ni to'xtating (0.3: lsof/netstat + kill).
Xato 2 — Brauzer cheksiz yuklanadi (spinner)
Sababi: res.end() chaqirilmagan 2.4-bob. Yechimi: har yo'lda res.end(); routing'da else (404) bo'lsin.
Xato 3 — ERR_STREAM_WRITE_AFTER_END
Sababi: res.end()dan keyin yana yozish, yoki writeHead kech 2.4-bob. Yechimi: enddan keyin yozmang; writeHead birinchi.
Xato 4 — req.body undefined
Sababi: body avtomatik parse qilinmaydi 2.8-bob. Yechimi: stream'dan o'qing (Misol 4) yoki Express + express.json() 5.6-bob.
Xato 5 — JSON parse xatosi (POST)
Sababi: noto'g'ri/bo'sh body (2.8, 2.13). Yechimi: try/catch + 400 javob (Misol 4).
Xato 6 — Cyrillic/o'zbek matn buzilib ko'rinadi
Sababi: charset yo'q (0.1: UTF-8). Yechimi: Content-Type: text/html; charset=utf-8.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- HTTP nazariyasi 0.4-bob: metod/status/header/URL — bu yerda kodga aylandi.
- Stream/Event 5.4-bob:
req(Readable),res(Writable),data/end. - Express 5.6-bob:
httpustiga qurilgan — routing/body/middleware avtomatlashtiradi. - REST API 5.7-bob: Misol 5 — REST asoslari.
- Validatsiya 5.9-bob: body o'qigach tekshirish.
- Xavfsizlik (5.20, 14): body o'lchami, CORS, headerlar.
- Deploy (10): graceful shutdown (Misol 7).
8. Eng yaxshi amaliyotlar (best practices)
- Har yo'lda
res.end()— javobni yakunlang; routing'daelse404 2.4-bob. writeHead(status+header)write/enddan oldin 2.4-bob.- JSON'da
Content-Type: application/json+charset=utf-8(0.1, 0.4). - Body'ni stream'dan o'qing (
req.bodyyo'q — 2.8); o'lchamni cheklang (DoS — 14). - To'g'ri status kodlar (201 Created, 204 No Content, 404, 400 — 0.4).
errorevent'ini boshqaring (req/res streamlar — 5.4).- Graceful shutdown (
server.close— Misol 7) — production (10). - Real loyihada Express/NestJS (5.6, 8) —
httpni faqat o'rganish/maxsus holat uchun 2.13-bob.
9. Amaliy loyiha: "Sof Node bilan REST API (Express'siz)"
http modulini chuqur tushunish uchun — Express'siz to'liq API.
Maqsad
Faqat core http modul bilan routing, body parsing, query, status kodlar va static fayl xizmatini qo'lda amalga oshirib, Express "ichini" tushunish.
Talablar (requirements)
- Server:
http.createServer,listen; so'rovlarni loglovchi (Misol 1). - Routing:
req.method+url.pathnamebilan qo'lda router (Misol 2, 2.6); noma'lum yo'lga 404. - REST CRUD:
/tasksresursi — GET (ro'yxat), GET/tasks/:id, POST (201), PUT/PATCH, DELETE (204) (Misol 5); xotirada massiv (keyin DB — 6). - Body parsing: POST/PUT body'ni stream'dan o'qib, JSON parse; o'lcham chegarasi (Misol 4, 2.8, 14).
- Query:
/tasks?done=true&page=2— filtr/sahifalash (Misol 3, 2.7). - Status kodlar: to'g'ri kodlar (200/201/204/400/404 — 0.4).
- Static fayl:
/publicpapkadan HTML/CSS stream bilan (Misol 6, 5.4). - Xato boshqaruvi: noto'g'ri JSON → 400; fayl yo'q → 404;
try/catch2.13-bob. - Graceful shutdown: SIGTERM'da toza yopilish (Misol 7).
- (Bonus) Oddiy "middleware" g'oyasi: har so'rovdan oldin ishlaydigan funksiya (log/auth) — Express middleware 5.6-bob ga tayyorgarlik.
Maslahatlar (hint)
req— Readable stream; body uchundata/end(5.4, 2.8).req.bodyYO'Q — qo'lda yig'ing (Misol 4).- Query:
new URL(req.url, ...)(2.7, 5.3). res.end()har yo'lda;writeHeadbirinchi 2.4-bob.:iduchunpathname.split("/")(Misol 5).- Content-Type + charset=utf-8 (6-xato).
- DoS: body o'lchami chegarasi (Misol 4, 14).
"Tayyor" mezonlari (acceptance criteria)
- Server ishlaydi, so'rovlarni loglaydi.
- To'liq CRUD (GET/POST/PUT/DELETE) to'g'ri status bilan.
- Body stream'dan o'qiladi, o'lcham cheklangan.
- Query bilan filtr/sahifalash ishlaydi.
- Static fayl stream bilan xizmat qilinadi.
- Noto'g'ri JSON/fayl yo'q xatolari to'g'ri boshqarilgan.
- Graceful shutdown ishlaydi.
- Hech bir so'rov "osilib" qolmaydi (res.end har joyda).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda 0.4 nazariyasini amalga oshirib, sof http modul bilan server qurdik:
http.createServer(handler)— TCP server;handlerhar so'rovda (5.1: event loop, 5.4: EventEmitter).req(IncomingMessage — Readable stream):method/url/headers; body — qo'lda stream'dan (data/end— 5.4, 2.8).res(ServerResponse — Writable stream):writeHead(status, headers)→write→end(majburiy).- Routing qo'lda (
req.method+url.pathname); query —URL5.3-bob; status kodlar 0.4-bob. - Static fayl — stream +
pipe5.4-bob; graceful shutdown (production). - Nega Express — bularning hammasini avtomatlashtiradi (
httpustida — 5.6).
Keyingi bob — 5.6-bob: Express.js — routing, middleware (chuqur), req/res, router, static fayllar. Sof httpning "og'ir"ligini his qildik; endi uni engillashtiradigan Express'ni o'rganamiz. Routing, middleware (Express'ning yuragi), req.body/req.params/req.query — hammasi avtomatik. Bu — kitobning eng amaliy va eng ko'p ishlatiladigan boblaridan biri.
Foydalanilgan rasmiy/ishonchli manbalar
- nodejs.org/api/http — createServer, IncomingMessage, ServerResponse, writeHead, end
- nodejs.org/learn — HTTP server yaratish
- MDN — HTTP (0.4: metod, status, header)
O'qiganingizni mustahkamlang
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!