Express middleware va next()
O’tgan darsda app.use(express.json())
qatorini yozdik va “hozircha shunday qabul qiling” dedik. Endi o’sha
qator nima qilishini ochamiz. U middleware — Express’dagi eng kuchli
tushuncha, chunki autentifikatsiya, log, xatolarni ushlash va forma
o’qish — hammasi shu mexanizmga tayanadi.
Muammo: takrorlanadigan kod
Tasavvur qiling, har so’rovni terminalga yozib borishingiz kerak. Bir
yo’li — har marshrutga console.log qo’shish:
app.get("/tasks", (request, response) => {
console.log("GET /tasks");
response.send("Vazifalar ro'yxati");
});
app.get("/users", (request, response) => {
console.log("GET /users");
response.send("Foydalanuvchilar ro'yxati");
});
Yigirmata marshrutda bu yigirmata takror. Bittasini unutsangiz, log to’liq bo’lmaydi. Middleware shu muammoni bitta joyda yechadi.
Middleware nima
So’rov serverga kelganda zanjir bo’ylab yuradi:
So'rov → middleware 1 → middleware 2 → marshrut → javob
Har bo’g’in ikki ish qila oladi: so’rovni o’zgartirish yoki
to’xtatish. express.json() birinchi turga kiradi — u so’rov tanasini
o’qib, request.body ni to’ldiradi va zanjirni davom ettiradi.
Birinchi middleware
Log yozadigan funksiyani o’zimiz yozamiz:
const express = require("express");
const app = express();
// Har so'rov haqida terminalga yozamiz
app.use((request, response, next) => {
console.log(`${request.method} ${request.url}`);
next();
});
app.get("/tasks", (request, response) => {
response.send("Vazifalar ro'yxati");
});
app.get("/users", (request, response) => {
response.send("Foydalanuvchilar ro'yxati");
});
app.listen(3000, () => {
console.log("Server ishga tushdi: http://localhost:3000");
});
Ikki so’rov yuboring:
curl http://localhost:3000/tasks
curl http://localhost:3000/users
Serverning terminalida:
GET /tasks
GET /users
Marshrutlarda console.log yo’q, lekin ikkalasi ham qayd etildi. Yangi
marshrut qo’shsangiz, u ham o’zidan-o’zi logga tushadi.
next() — zanjirning kaliti
next() chaqirilmasa nima bo’ladi? Sinab ko’ring:
// ❌ next() yo'q
app.use((request, response, next) => {
console.log(`${request.method} ${request.url}`);
});
app.get("/tasks", (request, response) => {
response.send("Vazifalar ro'yxati");
});
curl http://localhost:3000/tasks
Terminalda GET /tasks chiqadi, lekin curl javob kutib osilib
qoladi. Brauzerda ham sahifa cheksiz yuklanadi.
Zanjir tartibi
Middleware yozilgan tartibda ishlaydi. Tartibni ko’rish uchun ikkita qo’shamiz:
app.use((request, response, next) => {
console.log("1-middleware boshlandi");
next();
console.log("1-middleware tugadi");
});
app.use((request, response, next) => {
console.log("2-middleware");
next();
});
app.get("/tasks", (request, response) => {
console.log("Marshrut ishladi");
response.send("Vazifalar ro'yxati");
});
curl http://localhost:3000/tasks
1-middleware boshlandi
2-middleware
Marshrut ishladi
1-middleware tugadi
Oxirgi qator diqqatga sazovor: next() navbatdagi funksiyani chaqiradi
va u tugagach, boshqaruv qaytib keladi. Zanjir — bir tomonlama yo’l
emas, ichma-ich chaqiruvlar.
Amaliy xulosa: app.use() marshrutlardan yuqorida turishi kerak.
Pastda yozilsa, marshrut allaqachon javob yuborib bo’lgan bo’ladi va
middleware ishlamaydi.
// ❌ Kech qoldi — marshrut oldin javob beradi
app.get("/tasks", (request, response) => {
response.send("Vazifalar ro'yxati");
});
app.use(express.json());
Shu sababdan express.json() o’tgan darsda
fayl boshida yozilgan edi.
So’rovga ma’lumot qo’shish
Middleware request obyektiga yangi maydon qo’sha oladi — keyingi
bo’g’inlar uni o’qiydi:
app.use((request, response, next) => {
// So'rov kelgan vaqtni belgilaymiz
request.requestTime = new Date().toLocaleTimeString("uz-UZ");
next();
});
app.get("/tasks", (request, response) => {
response.send(`Vazifalar ro'yxati. So'rov vaqti: ${request.requestTime}`);
});
curl http://localhost:3000/tasks
Vazifalar ro'yxati. So'rov vaqti: 14:32:05
express.json() aynan shunday ishlaydi: tanani o’qib, request.body
maydonini qo’yadi va next() ni chaqiradi.
Zanjirni to’xtatish
Middleware so’rovni davom ettirmasdan javob berib to’xtatishi ham mumkin. Bu tekshiruvlar uchun ishlatiladi:
// "/admin" bo'limiga faqat maxfiy kalit bilan kiriladi
app.use("/admin", (request, response, next) => {
const key = request.query.key;
if (key !== "secret123") {
// next() chaqirilmaydi — zanjir shu yerda tugaydi
return response.status(403).json({ error: "Ruxsat yo'q" });
}
next();
});
app.get("/admin/stats", (request, response) => {
response.json({ users: 42, tasks: 128 });
});
Kalitsiz:
curl -i http://localhost:3000/admin/stats
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
{"error":"Ruxsat yo'q"}
Kalit bilan:
curl "http://localhost:3000/admin/stats?key=secret123"
{"users":42,"tasks":128}
403 — “kim ekaningiz aniq, lekin bu yerga ruxsatingiz yo’q”.
Marshrutga xos middleware
Middleware’ni bitta marshrutga ham ulash mumkin — uni app.get() ning
o’rta argumenti sifatida yozasiz:
// Faqat shu marshrut uchun tekshiruv
function checkId(request, response, next) {
const id = Number(request.params.id);
if (Number.isNaN(id)) {
return response.status(400).json({ error: "id son bo'lishi kerak" });
}
// Tekshirilgan sonni keyingi funksiyaga uzatamiz
request.taskId = id;
next();
}
app.get("/tasks/:id", checkId, (request, response) => {
response.json({ id: request.taskId, title: "Kitob o'qish" });
});
curl -i http://localhost:3000/tasks/abc
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{"error":"id son bo'lishi kerak"}
curl http://localhost:3000/tasks/5
{"id":5,"title":"Kitob o'qish"}
Marshrut funksiyasi endi tekshiruv bilan shug’ullanmaydi — unga faqat to’g’ri son yetib keladi. Bir xil tekshiruvni bir nechta marshrutda ishlatish mumkin.
morgan — tayyor log middleware
Log yozadigan middleware’ni o’zimiz yozdik, lekin amalda tayyor paket ishlatiladi.
npm install morgan
const express = require("express");
const morgan = require("morgan");
const app = express();
// "dev" — qisqa va rangli format
app.use(morgan("dev"));
app.get("/tasks", (request, response) => {
response.send("Vazifalar ro'yxati");
});
app.listen(3000, () => {
console.log("Server ishga tushdi: http://localhost:3000");
});
curl http://localhost:3000/tasks
Server terminalida:
GET /tasks 200 3.412 ms - 18
Bitta qatorda usul, manzil, holat kodi, javob vaqti va hajmi bor. O’z qo’lingiz bilan yozgan versiyada bu ma’lumotlarning yarmi yo’q edi.
morgan ham oddiy middleware: ichida request, response va next
bilan ishlaydigan o’sha funksiya turibdi. Uchinchi tomon paketlari sirli
emas — faqat siz yozganidan puxtaroq.
Amaliy mashq
express-app loyihasida davom eting:
- Usul va manzilni terminalga yozadigan middleware’ni
app.use()bilan ulang, ikki xil manzilga so’rov yuborib logni ko’ring; - Shu middleware’dagi
next()ni olib tashlang vacurljavob kutib osilib qolishini kuzating, so’ng qaytarib qo’ying; - Ikkita middleware qo’yib,
next()dan keyin hamconsole.logyozing va chiqish tartibini tushuntiring; request.requestTimemaydonini qo’shib, uni marshrut javobida chiqaring;/adminuchun kalit tekshiruvchi middleware yozing va uni kalitsiz hamda kalit bilan sinab ko’ring;morganni o’rnatib,app.use(morgan("dev"))qo’shing va o’z log’ingiz bilan solishtiring.
2-qadam eng qimmatlisi: next() unutilganda xato xabari chiqmaydi,
shuning uchun alomatni oldindan tanib olish kerak.
Qisqacha xulosa
- Middleware — so’rov marshrutga yetguncha ishlaydigan
(request, response, next)funksiyasi. app.use()uni zanjirga qo’shadi; manzil berilsa, faqat o’sha bo’limga ishlaydi.next()chaqirilmasa so’rov osilib qoladi — xato xabarisiz.- Middleware ikki ishdan birini bajaradi:
next()bilan davom ettiradi yoki javob yuborib to’xtatadi. - Zanjir yozilgan tartibda ishlaydi, shuning uchun
app.use()marshrutlardan yuqorida turadi. - Middleware
requestga yangi maydon qo’sha oladi —express.json()aynan shundayrequest.bodyni to’ldiradi. - Uchinchi tomon middleware’i (
morgan) o’zingiz yozganidek ishlaydi, faqat puxtaroq.
Keyingi darsda statik fayllar — HTML, CSS va rasmlarni serverdan berish, bu ham middleware orqali bajariladi.