Node.js http moduli bilan server

Node.js nima darsidagi jadvalning eng muhim qatori shu edi: brauzer so’rov yuboradi, Node.js so’rovni qabul qiladi. Shu paytgacha faqat fayl bilan ishladingiz. Endi qabul qiladigan tomonni yozasiz — tashqi paketsiz, Node.js ichidagi http moduli bilan.

Eng qisqa server

server.js faylini yarating:

const http = require("http");

const server = http.createServer((request, response) => {
  response.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
  response.end("Salom, bu Node.js serveri");
});

server.listen(3000, () => {
  console.log("Server ishlamoqda: http://localhost:3000");
});
node server.js
Server ishlamoqda: http://localhost:3000

Brauzerda http://localhost:3000 ni oching — matn chiqadi.

E’tibor bering: terminal bo’shamadi. Skript tugamadi, chunki server so’rov kutib turibdi. To’xtatish uchun terminalda Ctrl + C bosing.

HTTP va so’rov-javob darsida ko’rilgan almashinuvning server tomoni shu.

request va response

createServer ga berilgan funksiya har so’rovda chaqiriladi. Unga ikki obyekt keladi:

Obyekt Nima uchun
request Kelgan so’rov haqida ma’lumot
response Javob yuborish vositasi

So’rov haqida nima bilish mumkinligini ko’ramiz:

const http = require("http");

const server = http.createServer((request, response) => {
  console.log("Manzil:", request.url);
  console.log("Usul:", request.method);
  console.log("Brauzer:", request.headers["user-agent"]);

  response.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
  response.end("Tekshirildi");
});

server.listen(3000, () => {
  console.log("Server ishlamoqda: http://localhost:3000");
});

Brauzerda http://localhost:3000/about ni oching. Terminalda:

Manzil: /about
Usul: GET
Brauzer: Mozilla/5.0 ...

request.url faqat manzil qismini beradi — http://localhost:3000 qismisiz.

Marshrutlashni qo’lda yozamiz

Endi bir nechta manzilga javob beradigan server kerak. http modulida tayyor vosita yo’q — if bilan o’zingiz tekshirasiz.

notes-server.js:

const http = require("http");

const notes = [
  { id: 1, title: "Non sotib olish", isDone: false },
  { id: 2, title: "Kitob o'qish", isDone: true },
];

const server = http.createServer((request, response) => {
  const url = request.url;
  const method = request.method;

  if (url === "/" && method === "GET") {
    response.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
    response.end("<h1>Vazifalar xizmati</h1><p>Ro'yxat: /api/notes</p>");
    return;
  }

  if (url === "/api/notes" && method === "GET") {
    response.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
    response.end(JSON.stringify(notes));
    return;
  }

  response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
  response.end("Sahifa topilmadi");
});

server.listen(3000, () => {
  console.log("Server ishlamoqda: http://localhost:3000");
});

Brauzerda http://localhost:3000/api/notes ni oching:

[{"id":1,"title":"Non sotib olish","isDone":false},{"id":2,"title":"Kitob o'qish","isDone":true}]

Mavjud bo’lmagan manzil — http://localhost:3000/yoq:

Sahifa topilmadi

Har shoxda uch ish takrorlanadi: writeHead, end va return.

Holat kodlari

writeHead ning birinchi argumenti — holat kodi:

Kod Ma’nosi Qachon
200 OK So’rov bajarildi
201 Created Yangi yozuv yaratildi
400 Bad Request Kelgan ma’lumot noto’g’ri
404 Not Found Manzil topilmadi
500 Internal Server Error Serverda xato

Kodni brauzer DevTools’ining Network bo’limida ko’rish mumkin.

Manzildagi qiymatni ajratish

/search?q=kitob ko’rinishidagi so’rovdan kitob ni olish kerak bo’lsa, manzilni tahlil qilish zarur:

const http = require("http");

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

  if (parsedUrl.pathname === "/search" && request.method === "GET") {
    const query = parsedUrl.searchParams.get("q");

    response.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
    response.end(`Qidiruv so'zi: ${query}`);
    return;
  }

  response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
  response.end("Sahifa topilmadi");
});

server.listen(3000, () => {
  console.log("Server ishlamoqda: http://localhost:3000");
});

http://localhost:3000/search?q=kitob manzilida:

Qidiruv so'zi: kitob

request.url da ?q=kitob ham turadi, shuning uchun uni === bilan solishtirib bo’lmaydi — avval pathname ajratib olinadi.

POST so’rovini qabul qilish

Bu eng noqulay qismi. Kelgan ma’lumot bo’lak-bo’lak keladi — chunki so’rov tanasi ham oqim:

const http = require("http");

const notes = [
  { id: 1, title: "Non sotib olish", isDone: false },
];

const server = http.createServer((request, response) => {
  if (request.url === "/api/notes" && request.method === "POST") {
    let body = "";

    // Bo'laklarni yig'amiz
    request.on("data", (chunk) => {
      body += chunk;
    });

    // Hammasi kelgach tahlil qilamiz
    request.on("end", () => {
      try {
        const parsed = JSON.parse(body);

        const newNote = {
          id: notes.length + 1,
          title: parsed.title,
          isDone: false,
        };
        notes.push(newNote);

        response.writeHead(201, { "Content-Type": "application/json; charset=utf-8" });
        response.end(JSON.stringify(newNote));
      } catch (error) {
        response.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
        response.end(JSON.stringify({ error: "Noto'g'ri JSON" }));
      }
    });

    return;
  }

  response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
  response.end("Sahifa topilmadi");
});

server.listen(3000, () => {
  console.log("Server ishlamoqda: http://localhost:3000");
});

Tekshirish uchun boshqa terminal oynasini oching:

curl -X POST http://localhost:3000/api/notes -H "Content-Type: application/json" -d "{\"title\":\"Yangi vazifa\"}"
{"id":2,"title":"Yangi vazifa","isDone":false}

Buzuq ma’lumot yuborsangiz:

curl -X POST http://localhost:3000/api/notes -d "buzuq"
{"error":"Noto'g'ri JSON"}

EventEmitter va oqimlar darslaridagi data va end hodisalari shu yerda ishga tushdi. Bitta POST so’rovini qabul qilish uchun o’n besh qator kod ketdi.

Kod nega bunchalik uzun

Yozganlaringizni sanab chiqamiz:

  • har javobda writeHead va Content-Type qo’lda yoziladi;
  • JSON JSON.stringify bilan qo’lda aylantiriladi;
  • marshrutlar uzun if zanjiriga aylanadi;
  • har shoxda return yozish esda turishi kerak;
  • POST tanasi bo’lak-bo’lak yig’iladi;
  • manzildagi qiymat qo’lda ajratiladi.

Ikkita manzil uchun kod chidasa bo’ladigan darajada. Yigirmata manzil, autentifikatsiya va formalar qo’shilsa, bu fayl boshqarib bo’lmas holga keladi.

Serverni to’xtatish va qayta ishga tushirish

Kodni o’zgartirsangiz, server o’zi yangilanmaydi. Har safar:

  1. Terminalda Ctrl + C bosing;
  2. node server.js ni qayta bering.

npm darsida ko’rgan nodemon shu ishni avtomatlashtiradi: faylni saqlaganingizda serverni o’zi qayta ishga tushiradi.

npm install --save-dev nodemon
npx nodemon server.js
[nodemon] watching path(s): *.*
[nodemon] starting `node server.js`
Server ishlamoqda: http://localhost:3000

Amaliy mashq

node-start papkasida bajaring:

  1. Bitta matn qaytaradigan server yozib, brauzerda localhost:3000 da oching;
  2. Serverni to’xtatmasdan ikkinchi marta ishga tushirib EADDRINUSE xatosini ko’ring, so’ng portni o’zgartiring;
  3. request.url va request.method ni terminalga chiqaring va turli manzillarni ochib kuzating;
  4. Ikkita manzilga javob beradigan marshrutlash yozing, qolgan hammasiga 404 qaytaring;
  5. /api/notes manzilida JSON.stringify bilan massiv qaytaring va Content-Type ni application/json qiling;
  6. Bitta if blokidagi return ni ataylab o’chirib, ERR_HTTP_HEADERS_SENT xatosini chiqaring, so’ng qaytaring.

6-qadam eng muhimi: bu xato sof http bilan ishlaganda eng ko’p vaqt yeydigan tuzoqlardan biri.

Qisqacha xulosa

  • http — o’rnatilgan modul: server yozish uchun paket kerak emas.
  • createServer ga berilgan funksiya har so’rovda chaqiriladi.
  • request.url va request.method marshrutlash uchun asos, tekshiruv qo’lda yoziladi.
  • Har if bloki return bilan tugaydi — aks holda ERR_HTTP_HEADERS_SENT chiqadi.
  • JSON javob uchun JSON.stringify va to’g’ri Content-Type o’zingizdan.
  • POST tanasi oqim sifatida data va end hodisalari bilan yig’iladi.
  • EADDRINUSE — port band: eski serverni to’xtating yoki portni o’zgartiring.

Keyingi darsda CLI dastur — bo’limdagi hamma bilimni birlashtiradigan yakuniy loyiha. Server yozishni qulayroq qiladigan yo’l esa Express nima darsida boshlanadi: xuddi shu vazifa ancha qisqa kod bilan yoziladi.

Bu dars foydali bo'ldimi?

marta ko'rildi