HTTP Server — http moduli, request, response

~20 daq · Node.js · Amaliy

Muammodan boshlaylik

Express, Fastify, NestJS — bularning barchasi ichida Node.js ning o'z http moduli ishlaydi. Siz har kuni ishlatadiganingiz aslida shu modulning ustiga qurilgan. Uni bir marta o'z qo'lingiz bilan yozsangiz — framework ichida nima sodir bo'layotgani tushuniladi, va muammo chiqganda qayerdan qidirishni bilasiz.


http moduli — asosiy server

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Salom, dunyo!');
});

server.listen(3000, () => {
  console.log('Server ishga tushdi: http://localhost:3000');
});

createServer — har yangi so'rov kelganda (req, res) callback ishga tushadi. listen — portni "tinglashni" boshlaydi.

res.writeHead(200, { ... }) — status kod va headerlar. res.end(...) — javobni yuboradi va ulanishni yopadi. end chaqirilmasa — brauzer javob kutib qotib qoladi.


req — so'rov ob'ekti

req — IncomingMessage klassi. Unda kelgan so'rov haqida hamma narsa bor.

const server = http.createServer((req, res) => {
  console.log(req.method);  // "GET", "POST", "PUT", "DELETE"
  console.log(req.url);     // "/users", "/api/products?page=2"
  console.log(req.headers); // { host: 'localhost:3000', 'user-agent': '...' }

  res.end('OK');
});

URL va query parametrlar

req.url da to'liq path bor — query string bilan birga. Ularni ajratish uchun URL konstruktori ishlatiladi:

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);

  console.log(url.pathname);           // "/api/users"
  console.log(url.searchParams.get('page')); // "2"
  console.log(url.searchParams.get('limit')); // "10"

  res.end('OK');
});

// So'rov: GET /api/users?page=2&limit=10

Body o'qish

req — Readable Stream. Body to'liq kelmagunicha bo'laklab keladi, shuning uchun yig'ib olinadi:

const server = http.createServer((req, res) => {
  if (req.method === 'POST') {
    let body = '';

    req.on('data', chunk => {
      body += chunk.toString(); // ← har bo'lak kelganda qo'shiladi
    });

    req.on('end', () => {
      // ← barcha bo'laklar keldi
      const data = JSON.parse(body);
      console.log(data); // { name: 'Jasur', email: '...' }

      res.writeHead(201, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ success: true, data }));
    });
  }
});

Bu pattern Express da express.json() middleware qiladi — siz yozmaysiz.


res — javob ob'ekti

res — ServerResponse klassi.

// Status va headerlar
res.writeHead(404, {
  'Content-Type': 'application/json',
  'X-Custom-Header': 'my-value',
});

// Yoki alohida
res.statusCode = 404;
res.setHeader('Content-Type', 'application/json');

// Javob yuborish
res.end(JSON.stringify({ error: 'Topilmadi' }));

// Yoki bo'laklarda yozish
res.write('Birinchi qism\n');
res.write('Ikkinchi qism\n');
res.end(); // ← oxirida albatta chaqiriladi

Routing — qo'lda

Express yo'q — route larni o'zingiz ajratishingiz kerak:

const http = require('http');

const users = [
  { id: 1, name: 'Jasur' },
  { id: 2, name: 'Malika' },
];

const server = http.createServer((req, res) => {
  const url    = new URL(req.url, `http://${req.headers.host}`);
  const path   = url.pathname;
  const method = req.method;

  res.setHeader('Content-Type', 'application/json');

  // GET /users
  if (path === '/users' && method === 'GET') {
    res.writeHead(200);
    res.end(JSON.stringify(users));
    return;
  }

  // GET /users/:id
  const match = path.match(/^\/users\/(\d+)$/);
  if (match && method === 'GET') {
    const user = users.find(u => u.id === Number(match[1]));
    if (!user) {
      res.writeHead(404);
      res.end(JSON.stringify({ error: 'Topilmadi' }));
      return;
    }
    res.writeHead(200);
    res.end(JSON.stringify(user));
    return;
  }

  // 404 — hech narsaga to'g'ri kelmadi
  res.writeHead(404);
  res.end(JSON.stringify({ error: "Yo'q bunday yo'l" }));
});

server.listen(3000, () => console.log('http://localhost:3000'));

Bu kodni ko'rgach Express nima qilishini aniqroq tushunasiz: route handler lar, req.params, res.json() — bularning barchasi http moduli ustida qurilgan syntactic sugar.


HTTPS server

HTTPS uchun SSL sertifikat kerak. Lokal ishlab chiqishda openssl bilan o'z-o'ziga imzolangan sertifikat yaratiladi:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
const https = require('https');
const fs    = require('fs');

const options = {
  key:  fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem'),
};

const server = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('HTTPS server ishlayapti');
});

server.listen(443);

Produksiyada sertifikatni Let's Encrypt yoki hosting provayder beradi — siz faqat fayllarning yo'lini ko'rsatasiz.


Server hodisalari

const server = http.createServer(handler);

// Xato ushlash
server.on('error', err => {
  if (err.code === 'EADDRINUSE') {
    console.error(`Port band! Boshqa port tanlang.`);
  } else {
    console.error(err);
  }
});

// Ulanish hodisasi
server.on('connection', socket => {
  console.log('Yangi ulanish:', socket.remoteAddress);
});

// Yopilganda
server.on('close', () => {
  console.log('Server yopildi');
});

server.listen(3000);

// Graceful shutdown — so'rovlarni tugatib yopish
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Barcha so\'rovlar yakunlandi');
    process.exit(0);
  });
});

EADDRINUSE — port allaqachon band. Ko'pincha avvalgi node prosessi hali ishlayapti.


Tez-tez uchraydigan xatolar

res.end() chaqirilmasa

// ❌ Brauzer javob kutib qotib qoladi
const server = http.createServer((req, res) => {
  if (req.url === '/users') {
    res.end(JSON.stringify(users));
  }
  // boshqa yo'llar uchun end yo'q — timeout
});

// ✅ Har doim javob qaytariladi
const server = http.createServer((req, res) => {
  if (req.url === '/users') {
    res.end(JSON.stringify(users));
    return; // ← keyingi kodga o'tmasligi uchun
  }
  res.writeHead(404);
  res.end('Topilmadi');
});

Headerdan keyin writeHead

// ❌ Header yuborilgandan keyin yana writeHead — xato
res.end('Salom');
res.writeHead(200); // Error: Cannot set headers after they are sent

// ✅ writeHead — end dan oldin
res.writeHead(200);
res.end('Salom');

Xulosa

http moduli — Node.js ning tarmoq qismi. Express, Fastify, NestJS shu modul ustiga qurilgan. Uni bir marta qo'lda yozsangiz — framework "sehrini" tushunasiz.

Eslab qoling:

  • http.createServer((req, res) => {}) — server yaratish
  • req.method, req.url, req.headers — so'rov ma'lumotlari
  • Body — req.on('data') va req.on('end') orqali o'qiladi
  • res.writeHead(statusCode, headers) — status va headerlar
  • res.end(data) — har doim chaqirilishi kerak
  • new URL(req.url, base) — URL va query parametrlarni ajratish
  • https moduli — http bilan bir xil, faqat sertifikat kerak

Keyingi dars

26-dars: Debugging — node --inspect, Chrome DevTools, breakpoint