Express forma va validatsiya

CRUD API darsida title bo’shligini tekshirdik — bitta if bilan. Haqiqiy formada maydon beshta bo’ladi: biri majburiy, biri son, biri email, biri uzunlik chegarasiga ega. Bitta if yetmaydi. Bu darsda formadan kelgan ma’lumotni qabul qilishni va uni tartibli tekshirishni ko’ramiz.

HTML forma ma’lumotni boshqacha yuboradi

public/form.html faylini yarating:

<!DOCTYPE html>
<html lang="uz">
  <head>
    <meta charset="UTF-8" />
    <title>Yangi vazifa</title>
  </head>
  <body>
    <h1>Yangi vazifa qo'shish</h1>

    <form action="/tasks" method="POST">
      <p>
        <label for="title">Sarlavha:</label>
        <input type="text" id="title" name="title" />
      </p>
      <p>
        <label for="priority">Muhimlik (1-5):</label>
        <input type="number" id="priority" name="priority" />
      </p>
      <button type="submit">Saqlash</button>
    </form>
  </body>
</html>

Forma teglari forma asoslari darsida ko’rilgan. Bu yerda ikki atribut muhim: action — ma’lumot qayerga boradi, method — qaysi usul bilan.

express.urlencoded()

So’rov va javob darsida express.json() ni uladik. Lekin HTML forma JSON yubormaydi — u boshqa formatdan foydalanadi.

const express = require("express");
const path = require("path");

const app = express();

app.use(express.static(path.join(__dirname, "public")));

// Ikki format uchun ikki middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.post("/tasks", (request, response) => {
  console.log(request.body);
  response.send("Qabul qilindi");
});

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

Brauzerda http://localhost:3000/form.html ni ochib, formani to’ldiring va Saqlash ni bosing. Server terminalida:

{ title: "Kitob o'qish", priority: '3' }

Hamma qiymat matn bo’lib keladi

Yuqoridagi natijaga qarang: priority: '3' — tirnoq ichida.

<input type="number"> bo’lsa ham, HTTP orqali hamma narsa matn sifatida yuboriladi. Bu chalkashlik manbai:

const priority = request.body.priority;  // "3"

console.log(priority + 1);          // "31" — matn birikmasi
console.log(Number(priority) + 1);  // 4 — to'g'ri

Shuning uchun tekshiruvning birinchi qadami — kerakli turga aylantirish.

Foydalanuvchi kiritganiga ishonmaslik

Tekshiruvni qo’lda yozish

Har xatoni alohida javob bilan qaytarish noqulay: foydalanuvchi birinchi xatoni tuzatadi, keyin ikkinchisini ko’radi. Yaxshisi — hamma xatoni bir yo’la yig’ish.

// Vazifa ma'lumotini tekshiradi, xatolar ro'yxatini qaytaradi
function validateTask(body) {
  const errors = [];

  const title = typeof body.title === "string" ? body.title.trim() : "";
  const priority = Number(body.priority);

  if (title === "") {
    errors.push({ field: "title", message: "Sarlavha bo'sh bo'lmasin" });
  } else if (title.length > 100) {
    errors.push({ field: "title", message: "Sarlavha 100 belgidan oshmasin" });
  }

  if (Number.isNaN(priority)) {
    errors.push({ field: "priority", message: "Muhimlik son bo'lishi kerak" });
  } else if (priority < 1 || priority > 5) {
    errors.push({ field: "priority", message: "Muhimlik 1 va 5 orasida bo'lsin" });
  }

  return errors;
}

Funksiya uch xil tekshiruvni qamraydi: mavjudlik (bo’shmi), uzunlik (juda uzun emasmi) va tur bilan oraliq (son va 1-5 orasidami).

typeof body.title === "string" tekshiruvi ham kerak: maydon umuman yuborilmasa, body.title qiymati undefined bo’ladi va .trim() chaqirilsa server yiqiladi.

Endi uni marshrutga ulaymiz:

let tasks = [];
let nextId = 1;

app.post("/tasks", (request, response) => {
  const errors = validateTask(request.body);

  if (errors.length > 0) {
    // 400 — foydalanuvchi xatosi, qaysi maydon ekanini ham aytamiz
    return response.status(400).json({ errors: errors });
  }

  const task = {
    id: nextId,
    title: request.body.title.trim(),
    priority: Number(request.body.priority),
    isDone: false,
  };

  nextId = nextId + 1;
  tasks.push(task);

  response.status(201).json(task);
});

Noto’g’ri ma’lumot bilan sinang:

curl -i -X POST http://localhost:3000/tasks \
  -H "Content-Type: application/json" \
  -d '{"title":"","priority":"999"}'
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8

{"errors":[{"field":"title","message":"Sarlavha bo'sh bo'lmasin"},{"field":"priority","message":"Muhimlik 1 va 5 orasida bo'lsin"}]}

To’g’ri ma’lumot bilan:

curl -i -X POST http://localhost:3000/tasks \
  -H "Content-Type: application/json" \
  -d '{"title":"Kitob oqish","priority":"2"}'
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8

{"id":1,"title":"Kitob oqish","priority":2,"isDone":false}

Javobdagi priority endi tirnoqsiz — u songa aylantirilib saqlandi.

Tekshiruvni middleware qilish

validateTask ni middleware shakliga o’tkazsak, marshrut faqat o’z ishi bilan shug’ullanadi:

function checkTask(request, response, next) {
  const errors = validateTask(request.body);

  if (errors.length > 0) {
    return response.status(400).json({ errors: errors });
  }

  next();
}

app.post("/tasks", checkTask, (request, response) => {
  const task = {
    id: nextId,
    title: request.body.title.trim(),
    priority: Number(request.body.priority),
    isDone: false,
  };

  nextId = nextId + 1;
  tasks.push(task);

  response.status(201).json(task);
});

Marshrut funksiyasi qisqardi va tekshiruvni boshqa marshrutlarda (masalan PUT /tasks/:id) qayta ishlatish mumkin bo’ldi.

Formadan keyin yo’naltirish

Forma brauzerdan yuborilganda JSON javob g’alati ko’rinadi — foydalanuvchi ekranda xom matn ko’radi. Odatda yo’naltirish qilinadi:

app.post("/tasks", checkTask, (request, response) => {
  const task = {
    id: nextId,
    title: request.body.title.trim(),
    priority: Number(request.body.priority),
    isDone: false,
  };

  nextId = nextId + 1;
  tasks.push(task);

  // Saqlandi — foydalanuvchini ro'yxat sahifasiga yuboramiz
  response.redirect("/tasks-list.html");
});

Nega shunday qilinadi: yo’naltirishsiz foydalanuvchi sahifani yangilasa, brauzer POST so’rovini qayta yuboradi va bir xil vazifa ikki marta qo’shiladi. Yo’naltirish bu muammoni yechadi, chunki oxirgi so’rov GET bo’lib qoladi.

express-validator

Tekshiruvlar ko’payganda validateTask uzayib ketadi. Tayyor paket bu ishni qisqartiradi:

npm install express-validator
const { body, validationResult } = require("express-validator");

app.post(
  "/tasks",
  body("title").trim().notEmpty().withMessage("Sarlavha bo'sh bo'lmasin"),
  body("title").isLength({ max: 100 }).withMessage("Sarlavha 100 belgidan oshmasin"),
  body("priority").isInt({ min: 1, max: 5 }).withMessage("Muhimlik 1 va 5 orasida bo'lsin"),
  (request, response) => {
    const result = validationResult(request);

    if (!result.isEmpty()) {
      return response.status(400).json({ errors: result.array() });
    }

    response.status(201).json({ message: "Vazifa qabul qilindi" });
  }
);

Har body(...) qatori — alohida middleware. Ular tekshiruv natijasini to’playdi, validationResult esa yig’ilgan xatolarni beradi.

Yondashuv Qachon qulay
Qo’lda yozilgan funksiya Maydon kam, qoidalar oddiy
express-validator Maydon ko’p, qoida murakkab

Qo’lda yozishni avval o’rganish foydali: paket parda ortida aynan shu ishni bajaradi.

Amaliy mashq

express-app loyihasida davom eting:

  1. public/form.html da title va priority maydonli forma yarating;
  2. express.urlencoded({ extended: true }) ni ulab, formani yuboring va request.body ni terminalda ko’ring;
  3. name atributini bitta maydondan olib tashlang — u request.body da yo’qolishini tasdiqlang, so’ng qaytaring;
  4. validateTask funksiyasini yozib, bo’sh sarlavha va priority=999 bilan 400 javobini oling;
  5. Tekshiruvni checkTask middleware’iga o’tkazib, marshrutga ulang;
  6. curl orqali brauzerni chetlab o’tib bo’sh title yuboring va server tekshiruvi baribir ishlashini ko’ring.

6-qadam darsning asosiy g’oyasini isbotlaydi: HTML’dagi required to’sib qololmaydi, server tekshiruvi esa to’sadi.

Qisqacha xulosa

  • HTML forma JSON emas, x-www-form-urlencoded formatida yuboradi — express.urlencoded() kerak.
  • request.body kalitlari name atributidan olinadi; name bo’lmasa maydon yuborilmaydi.
  • HTTP orqali kelgan hamma qiymat matn — sonni Number() bilan aylantiring.
  • Brauzerdagi required himoya emas: curl uni chetlab o’tadi, tekshiruv serverda takrorlanishi shart.
  • Xatolarni massivga yig’ib, field va message bilan qaytaring — frontend ularni maydonlarga bog’lay oladi.
  • Noto’g’ri ma’lumotga 400 javobi beriladi.
  • Tekshiruvni middleware qilsangiz, uni bir nechta marshrutda qayta ishlatasiz; express-validator shu ishni qisqartiradi.

Keyingi darsda EJS shabloni — JSON o’rniga to’laqonli HTML sahifa qaytarish va uni xavfsiz to’ldirish.

Bu dars foydali bo'ldimi?

marta ko'rildi