13-bo‘lim

Oraliq qatlamlar (middleware)

next() qanday ishlaydi, tartibning ahamiyati, express.json, o'z qatlamingizni yozish, xato qatlami va so'rovga ma'lumot biriktirish.

🕑 11 daqiqa o‘qish 📄 517 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. next() zanjiri
  2. Tartib hamma narsani hal qiladi
  3. express.json
  4. O'z qatlamingiz
  5. So'rovga ma'lumot biriktirish
  6. Faqat ma'lum yo'lga
  7. Xato qatlami
  8. Qatlam tartibi
  9. Xulosa

Oraliq qatlam (middleware) - so'rov bilan javob orasida turadigan funksiya. U so'rovni ko'radi, o'zgartiradi va keyingisiga uzatadi.

Express ning deyarli hamma imkoniyati aslida oraliq qatlam.

next() zanjiri #

JavaScript
import express from "express";

const app = express();
const izlar = [];

app.use((sorov, javob, keyingi) => {
    izlar.push("birinchi qatlam");
    keyingi();
});

app.use((sorov, javob, keyingi) => {
    izlar.push("ikkinchi qatlam");
    keyingi();
});

app.get("/", (sorov, javob) => {
    izlar.push("ishlovchi");
    javob.json({ izlar });
});

const server = app.listen(0);
const port = server.address().port;

console.log(await (await fetch(`http://localhost:${port}/`)).json());

server.close();
Natija
{ izlar: [ 'birinchi qatlam', 'ikkinchi qatlam', 'ishlovchi' ] }

Har bir qatlam uch argument oladi: (sorov, javob, keyingi).

keyingi() chaqirilmasa, zanjir to'xtaydi va so'rov osilib qoladi.

next() ni unutish - so'rov abadiy osiladi

Bu eng ko'p uchraydigan xato:

JavaScript
app.use((sorov, javob, keyingi) => {
    console.log(sorov.method);
    // keyingi() UNUTILDI
});

Server xato bermaydi, jurnalda hech narsa ko'rinmaydi - so'rov shunchaki javobsiz qoladi va brauzer kutishda davom etadi.

Qoida: qatlam yo keyingi() ni chaqirsin, yo javob yuborsin. Ikkalasini ham qilmasa - bu xato. Ikkalasini ham qilsa, bu ham xato:

Natija
Error: Cannot set headers after they are sent to the client

Tartib hamma narsani hal qiladi #

JavaScript
import express from "express";

const app = express();

app.get("/erta", (s, j) => j.json({ javob: "marshrutdan" }));

app.use((sorov, javob, keyingi) => {
    javob.set("X-Qatlam", "ishladi");
    keyingi();
});

app.get("/kech", (s, j) => j.json({ javob: "qatlamdan keyin" }));

const server = app.listen(0);
const port = server.address().port;
const asos = `http://localhost:${port}`;

const erta = await fetch(asos + "/erta");
console.log("erta:", erta.headers.get("x-qatlam"));

const kech = await fetch(asos + "/kech");
console.log("kech:", kech.headers.get("x-qatlam"));

server.close();
Natija
erta: null
kech: ishladi

Qatlam faqat o'zidan keyin e'lon qilingan marshrutlarga ta'sir qiladi.

Shuning uchun umumiy qatlamlar - jurnal, xavfsizlik, JSON tahlili - har doim eng yuqorida turadi.

express.json #

JavaScript
import express from "express";

const app = express();

app.use(express.json({ limit: "100kb" }));

app.post("/talabalar", (sorov, javob) => {
    javob.status(201).json({
        qabul: sorov.body,
        turi: typeof sorov.body,
    });
});

const server = app.listen(0);
const port = server.address().port;

const javob = await fetch(`http://localhost:${port}/talabalar`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ ism: "Nodira", ball: 91 }),
});

console.log(javob.status);
console.log(await javob.json());

server.close();
Natija
201
{ qabul: { ism: 'Nodira', ball: 91 }, turi: 'object' }

express.json() - 10-bo'limda qo'lda yozgan ishimizni bajaradi: tanani yig'adi, JSON ga aylantiradi va sorov.body ga qo'yadi.

limit ni har doim bering

express.json() ning odatiy chegarasi - 100 KB. U yomon emas, lekin uni ochiq yozish yaxshi odat: shunda o'quvchi chegara borligini biladi.

Chegaradan oshgan so'rov 413 holati bilan rad etiladi - bu 10-bo'limda qo'lda yozgan himoyamiz.

Agar fayl yuklash kerak bo'lsa, express.json noto'g'ri vosita - u faqat JSON uchun. Fayllar uchun multipart/form-data ni tushunadigan alohida paket kerak bo'ladi.

O'z qatlamingiz #

JavaScript
import express from "express";

const app = express();
const jurnal = [];

function jurnalla(sorov, javob, keyingi) {
    jurnal.push(`${sorov.method} ${sorov.path}`);
    keyingi();
}

function faqatJson(sorov, javob, keyingi) {
    if (sorov.method === "POST" && !sorov.is("application/json")) {
        javob.status(415).json({ xato: "faqat JSON qabul qilinadi" });
        return;
    }
    keyingi();
}

app.use(jurnalla);
app.use(faqatJson);

app.get("/", (s, j) => j.json({ holat: "yaxshi" }));
app.post("/", (s, j) => j.json({ holat: "qabul qilindi" }));

const server = app.listen(0);
const port = server.address().port;
const asos = `http://localhost:${port}`;

await fetch(asos + "/");

const notogri = await fetch(asos + "/", {
    method: "POST",
    headers: { "Content-Type": "text/plain" },
    body: "oddiy matn",
});
console.log(notogri.status, await notogri.json());
console.log("jurnal:", jurnal);

server.close();
Natija
415 { xato: 'faqat JSON qabul qilinadi' }
jurnal: [ 'GET /', 'POST /' ]

sorov.is(tur) - Content-Type sarlavhasini tekshiradi. 415 - "qo'llab-quvvatlanmaydigan format" degan holat kodi.

So'rovga ma'lumot biriktirish #

JavaScript
import express from "express";

const app = express();

app.use((sorov, javob, keyingi) => {
    sorov.sorovId = "sinov-123";
    sorov.boshlanish = 1000;
    keyingi();
});

app.use((sorov, javob, keyingi) => {
    javob.set("X-Sorov-Id", sorov.sorovId);
    keyingi();
});

app.get("/", (sorov, javob) => {
    javob.json({ id: sorov.sorovId, boshlanish: sorov.boshlanish });
});

const server = app.listen(0);
const port = server.address().port;

const javob = await fetch(`http://localhost:${port}/`);
console.log(javob.headers.get("x-sorov-id"));
console.log(await javob.json());

server.close();
Natija
sinov-123
{ id: 'sinov-123', boshlanish: 1000 }

Qatlam sorov obyektiga xossa qo'shishi mumkin va u zanjir bo'ylab keyingi hammasiga yetib boradi.

Bu odatiy naqsh: autentifikatsiya qatlami sorov.foydalanuvchi ni qo'yadi, marshrutlar esa undan foydalanadi (17-bo'lim).

Faqat ma'lum yo'lga #

JavaScript
import express from "express";

const app = express();

app.use("/admin", (sorov, javob, keyingi) => {
    javob.set("X-Himoya", "bor");
    keyingi();
});

app.get("/admin/panel", (s, j) => j.json({ sahifa: "panel" }));
app.get("/ochiq", (s, j) => j.json({ sahifa: "ochiq" }));

const server = app.listen(0);
const port = server.address().port;
const asos = `http://localhost:${port}`;

const admin = await fetch(asos + "/admin/panel");
console.log("admin:", admin.headers.get("x-himoya"));

const ochiq = await fetch(asos + "/ochiq");
console.log("ochiq:", ochiq.headers.get("x-himoya"));

server.close();
Natija
admin: bor
ochiq: null

app.use(yol, qatlam) - qatlamni faqat o'sha prefiks bilan boshlanadigan yo'llarga qo'llaydi.

Xato qatlami #

JavaScript
import express from "express";

const app = express();

app.use(express.json());

app.get("/buzuq", async (sorov, javob) => {
    throw new Error("ichki nosozlik: parol=maxfiy");
});

app.get("/notogri", (sorov, javob, keyingi) => {
    const xato = new Error("id noto'g'ri");
    xato.holat = 400;
    keyingi(xato);
});

app.use((xato, sorov, javob, keyingi) => {
    const holat = xato.holat ?? 500;
    javob.status(holat).json({
        xato: holat === 500 ? "ichki server xatosi" : xato.message,
    });
});

const server = app.listen(0);
const port = server.address().port;
const asos = `http://localhost:${port}`;

const buzuq = await fetch(asos + "/buzuq");
console.log(buzuq.status, await buzuq.json());

const notogri = await fetch(asos + "/notogri");
console.log(notogri.status, await notogri.json());

server.close();
Natija
500 { xato: 'ichki server xatosi' }
400 { xato: "id noto'g'ri" }
Xato qatlami TO'RTTA argument oladi

Bu Express dagi eng nozik qoida:

JavaScript
app.use((xato, sorov, javob, keyingi) => { ... });

Express qatlamni argumentlar soni bo'yicha ajratadi. Uchta argument - oddiy qatlam, to'rtta - xato qatlami.

Agar keyingi ni yozmasangiz:

JavaScript
app.use((xato, sorov, javob) => { ... });   // ODDIY qatlam!

Express buni xato qatlami deb bilmaydi va u hech qachon ishlamaydi. Ishlatmasangiz ham, to'rtinchi argumentni yozing.

Yana ikki qoida:

  1. Xato qatlami eng oxirida turishi kerak.
  2. 500 xatolarida xato.message ni mijozga bermang - yuqoridagi misolda unda parol bor edi. Jurnalga to'liq yozing, mijozga umumiy xabar bering.

Qatlam tartibi #

So'rovning yo'li So'rov Xavfsizlik helmet, cors Tahlil express.json Jurnal so'rovni yozish Autentifikatsiya kim ekanini aniqlash Marshrut asosiy ish 404 qatlami mos kelmadi Xato qatlami to'rt argument Umumiy qatlamlar yuqorida, marshrutlar o'rtada, 404 va xato qatlami esa eng oxirida. har bir qatlam keyingi() ni chaqirmasa, zanjir uziladi
Amaliy topshiriq
  1. Ikkita qatlam yozib, tartibini kuzating.
  2. keyingi() ni unutib, so'rov osilishini ko'ring.
  3. Qatlamni marshrutdan keyin qo'yib, ta'sir qilmasligini ko'ring.
  4. express.json bilan tanani o'qing.
  5. limit ni kichik qilib, 413 ni oling.
  6. Content-Type ni tekshiradigan qatlam yozing.
  7. sorov ga xossa qo'shib, marshrutda ishlating.
  8. Qatlamni faqat /admin yo'liga qo'llang.
  9. To'rt argumentli xato qatlamini yozing.
  10. Uchinchi argumentni olib tashlab, ishlamay qolishini ko'ring.

Xulosa #

  • Oraliq qatlam - (sorov, javob, keyingi) funksiyasi; Express ning ko'p imkoniyati shundan iborat.
  • Qatlam yo keyingi() ni chaqirsin, yo javob yuborsin - ikkalasi ham bo'lmasa, so'rov osiladi.
  • Qatlam faqat o'zidan keyingi marshrutlarga ta'sir qiladi - umumiylarini yuqoriga qo'ying.
  • express.json({ limit }) tanani o'qiydi va hajmni cheklaydi.
  • Qatlam sorov ga xossa qo'shib, uni zanjir bo'ylab uzatishi mumkin.
  • app.use(yol, qatlam) - faqat o'sha prefiks uchun.
  • Xato qatlami to'rtta argument oladi va eng oxirida turadi; keyingi ishlatilmasa ham yoziladi.

Keyingi bo'limda formalar va validatsiyani o'rganamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.