IlmHamroh
JavaScript Full-stack/25-qism. HTTP, Express va REST API11/51-dars15 daqiqa
Mundarija (28)

Express res obyekti: res.status, res.json, res.send, sendStatus, redirect, sendFile va headersSent

Qisqacha: res — javob yozish uchun. Eng ko'p ishlatiladiganlari: res.status(201).json(obyekt) (zanjir), res.send() (turini o'zi tanlaydi: satr — HTML, obyekt — JSON, Buffer — baytlar), res.sendStatus(204), res.redirect(), res.set() va res.location() (sarlavhalar), res.sendFile() va res.download() (fayl), res.cookie() va res.locals (so'rov davomidagi ma'lumot). Ikki qat'iy qoida bor. Javobni bir marta yuborasiz — ikkinchisi ERR_HTTP_HEADERS_SENT beradi. res.json() funksiyani to'xtatmaydi, undan keyingi kod ham ishlaydi — return qo'ying. Biz sinadik: sendFile ga .. li yo'l berilsa, Express 403 qaytaradi, lekin xato ishlovchi bo'lmasa javobga serverdagi fayl yo'llari bilan to'liq stack trace chiqadi.

Bu darsda

  • res.status().json() zanjiri qanday ishlashini va res.send() qaysi Content-Type ni tanlashini bilasiz.
  • 201 + Location, 204, yo'naltirish javoblarini to'g'ri qaytarasiz.
  • sendFile va download bilan faylni xavfsiz berasiz.
  • res.cookie, res.set, res.locals ni ishlatasiz.
  • headersSent va ERR_HTTP_HEADERS_SENT xatosini tushunib, uning oldini olasiz.

Oldin bilishingiz kerak: req obyekti, Express'ga kirish, Static fayl server, HTTP metodlari va status kodlari.

1. Nega bu kerak?

Qo'lda routing darsida javob yozish uchun yordamchi yozgan edik: json(res, holat, malumot, sarlavhalar). Ichida — JSON.stringify, Buffer.byteLength, writeHead, end. Har API'da bir xil kod. Express buni res ga metodlar sifatida qo'yadi.

Lekin metodlar ko'p, va ular nozik farq qiladi. res.send("ok") va res.json("ok") turli Content-Type beradi. res.sendStatus(204) va res.status(204) — biri javobni yuboradi, ikkinchisi yubormaydi. Bir ishlovchida ikki marta javob yozish — server logida qizil xato. Bu dars — res metodlarining aniq xaritasi.

O'xshatish: restoran oshpazi buyurtmani tayyorlab, ofitsiantga beradi. Laganga yorliq yopishtiradi (status, sarlavhalar), keyin ovqatni qo'yadi (tana) va laganni zalga chiqaradi. Lagan chiqib ketgach, yorlig'ini almashtirib bo'lmaydi (headersSent). Bitta buyurtmaga ikkinchi laganni chiqarish esa — xato.

flowchart TD
  A["Nima qaytaramiz?"] --> B{"Tana bormi?"}
  B -- "yo'q" --> C["res.sendStatus(204)"]
  B -- "JSON" --> D["res.status(kod).json(obyekt)"]
  B -- "fayl" --> E["res.sendFile / res.download<br/>{ root }"]
  B -- "boshqa manzil" --> F["res.redirect(308, url)"]
  D --> G["yuborildi: headersSent = true"]
  C --> G
  E --> G
  F --> G

Har yo'l oxirida bitta holat: javob yuborildi va qaytarib bo'lmaydi. Dars shu to'rt shoxni birma-bir ochadi.

2. Status, sarlavhalar va tana

2.1 Zanjir

Express'da res.status(201) javobni yubormaydi — faqat statusni yozib qo'yadi va res ning o'zini qaytaradi. Shuning uchun metodlarni zanjir qilish mumkin:

js
res.status(201).location("/vazifalar/7").json({ id: 7 });

Zanjirdagi oxirgi metod (json, send, end) javobni yuboradi. Bu naqshni kichik model bilan ko'raylik. Brauzerda ham ishlaydi:

js
class Javob {
  statusCode = 200;
  sarlavhalar = {};
  headersSent = false;
  status(kod) {
    this.statusCode = kod;
    return this; // zanjir shu bilan ishlaydi
  }
  set(nom, qiymat) {
    if (this.headersSent) throw new Error("ERR_HTTP_HEADERS_SENT");
    this.sarlavhalar[nom] = qiymat;
    return this;
  }
  json(qiymat) {
    this.set("Content-Type", "application/json; charset=utf-8");
    this.headersSent = true;
    console.log(this.statusCode, JSON.stringify(this.sarlavhalar));
    console.log(JSON.stringify(qiymat));
    return this;
  }
}

const res = new Javob();
res.status(201).set("Location", "/vazifalar/7").json({ id: 7 });
try {
  res.json({ ikkinchi: true });
} catch (e) {
  console.log(e.message);
}

Konsolda:

text
201 {"Location":"/vazifalar/7","Content-Type":"application/json; charset=utf-8"}
{"id":7}
ERR_HTTP_HEADERS_SENT

Har metod return this qiladi — zanjirning siri shu. json dan keyin headersSent true: ikkinchi json sarlavha qo'yishga uringanda xato beradi. Haqiqiy Express xuddi shunday — pastda haqiqiy xato matnini ko'ramiz.

2.2 res.send() turini o'zi tanlaydi

Kanon tajribasi (Express 5.3.0, fetch bilan; ustunlar — yo'l, status, Content-Type, tana). Uchinchi ustunga — Content-Type ga qarang:

text
/send/satr → 200 text/html; charset=utf-8  "salom"
/send/obyekt → 200 application/json; charset=utf-8  "{\"a\":1}"
/send/buffer → 200 application/octet-stream  "bayt"
/send/son → 204 -  ""
/send/redirect → 301 text/plain; charset=utf-8 /q "Moved Permanently. Redirecting to /q"
Chaqiruv Content-Type Izoh
res.send("salom") text/html satr — HTML deb hisoblanadi!
res.send({ a: 1 }) application/json ichida res.json
res.send(Buffer.from("bayt")) application/octet-stream baytlar
res.sendStatus(204) — tanasiz
res.redirect(301, "/q") text/plain + Location qisqa matn tana bilan

Birinchi qator — tuzoq. API'dan res.send("Vazifa topilmadi") qaytarsangiz, brauzer uni HTML deb ko'radi. Matn ichida <script> bo'lsa va matn foydalanuvchidan kelgan bo'lsa — XSS xavfi. JSON API'da doim res.json() ishlating. Oddiy matn kerak bo'lsa — res.type("text/plain").send(...).

res.json(qiymat) ning res.send(obyekt) dan farqi: json satr va sonni ham JSON qilib yuboradi (res.json("ok") → "ok" qo'shtirnoq bilan, application/json).

2.3 Status kodli javoblar

Holat Kod
Yaratildi res.status(201).location(url).json(yangi)
Tanasiz muvaffaqiyat res.sendStatus(204)
Yo'naltirish res.redirect(308, "/v1/vazifalar")
Xato res.status(422).json({ xato }) — yoki throw (middleware darsi)

res.sendStatus(204) — res.status(204).send("No Content") ning qisqartmasi. 204 da tana bo'lmaydi, Node uni tashlab yuboradi. Kanon jonli tekshiruvida bir qiziq iz qoldi:

text
HTTP/1.1 204 No Content
ETag: W/"a-bAsFyilMr4Ra1hIU5PyoyFRunpI"
Connection: keep-alive
Keep-Alive: timeout=65

W/"a-…" — a = 10 bayt, ya'ni "No Content" matnining ETag'i. Express ETag'ni tana tashlanishidan oldin hisoblagan. Zararsiz, lekin "Express har javobga ETag qo'yadi" degan fikrning yana bir dalili. Biz ham o'z sinovimizda aynan shu qiymatni oldik.

res.redirect() sukut bo'yicha 302 beradi. Doimiy ko'chish uchun 301 yoki 308. Metod va tana saqlanishi kerak bo'lsa — 307/308 (HTTPS darsidagi yo'naltirish).

Tekshirib ko'ring: Ishlovchi res.status(404) bilan tugadi, boshqa hech narsa chaqirilmadi. Mijoz nimani oladi?

Javob

Hech narsani — so'rov osilib qoladi. status() faqat kodni yozib qo'yadi, javob yuborilmaydi. Mijoz o'z timeout'i tugaguncha kutadi. Serverdagi requestTimeout bu yerda yordam bermaydi: u faqat so'rovni qabul qilish vaqtini cheklaydi. Biz sinadik (Node 24.21.0): requestTimeout: 1000 li server javob bermadi, fetch 4 s dan keyin o'zining TimeoutError i bilan to'xtadi. To'g'risi — res.sendStatus(404) yoki res.status(404).json({...}).

3.1 res.set, res.location, res.type

js
res.set("X-Sorov-Id", "abc-123");          // bitta sarlavha
res.set({ "Cache-Control": "no-store" });  // bir nechta
res.location("/vazifalar/7");              // Location
res.type("text/plain");                    // qisqa nom bilan
res.append("Vary", "Origin");              // mavjudiga qo'shish

Biz ishga tushirdik: res.set("X-Sorov-Id", "abc-123").status(201).json({ ok: true }) → javobda x-sorov-id: abc-123, status 201. res.status(201).location("/vazifalar/7").json({ id: 7 }) → location: /vazifalar/7.

res.cookie(nom, qiymat, opsiyalar) — Set-Cookie sarlavhasini yasaydi. Biz sinadik:

js
res.cookie("til", "uz", { httpOnly: true, sameSite: "lax",
  maxAge: 60_000 });

Natija sarlavhasi:

text
set-cookie: til=uz; Max-Age=60; Path=/; Expires=Sat, 24 Oct 2026 14:15:08 GMT; HttpOnly; SameSite=Lax

maxAge millisekundda beriladi, sarlavhada esa soniyada (Max-Age=60). Path=/ va Expires ni Express o'zi qo'shdi. Atributlarning ma'nosi (HttpOnly, SameSite, Secure) — cookie chuqur darsida. vazifalar-api da cookie yo'q — u faqat JSON va (keyinroq) token bilan ishlaydi.

4. Fayl berish: sendFile va download

4.1 root bilan

res.sendFile(yol, { root }) — bitta faylni beradi: MIME, Content-Length, ETag, Range, 304 — static fayl darsidagi hamma narsa ichida. Biz sinadik — ikki so'rov, bir xil fayl. Ikkinchi qatordagi qo'shimcha sarlavhani toping:

text
/menyu 200 "osh 35000\n"
    content-type: text/plain; charset=utf-8 | etag: W/"a-1a16e430595" | content-length: 10
/yukla 200 "osh 35000\n"
    content-type: text/plain; charset=utf-8 | content-disposition: attachment; filename=bahor-menyu.txt | etag: W/"a-1a16e430595" | content-length: 10

res.download(fayl, "bahor-menyu.txt", { root }) farqi bitta sarlavhada: Content-Disposition: attachment. Brauzer faylni ko'rsatmaydi, yuklab oladi va ko'rsatilgan nom bilan saqlaydi.

4.2 Traversal va stack trace

sendFile ichida traversal himoyasi bor. Biz root papkasidan yuqoridagi faylni so'radik — res.sendFile("../e11.mjs", { root }). Javob 403 keldi, lekin tanasi kutilmagan edi (yo'llar … bilan qisqartirildi). at so'zidan keyingi qismlarga qarang:

text
/sir 403 "<!DOCTYPE html>…<pre>ForbiddenError: Forbidden<br> &nbsp; &nbsp;at createHttpError (C:\…\node_modules\send\index.js:861:12)<br> …at file:///C:/…/e11.mjs:10:7…"

Nima bo'ldi? Fayl berilmadi — himoya ishladi. Lekin xatoni hech kim ushlamadi va Express'ning sukut xato ishlovchisi javob yozdi. U NODE_ENV production bo'lmaganda to'liq stack trace chiqaradi: serverdagi papka yo'llari, kutubxona nomlari, fayl va qator raqamlari. Hujumchi uchun bu xarita. Ikki xulosa:

  1. O'z xato ishlovchingiz bo'lsin — JSON, ichki tafsilotsiz (middleware darsida yozamiz).
  2. sendFile ning uchinchi argumenti — callback. Unda xatoni o'zingiz ushlaysiz (3-mashq).

root siz sendFile faqat mutlaq yo'l qabul qiladi va himoya qilmaydi: res.sendFile(req.params.nom) — xato beradi, res.sendFile(join(papka, req.params.nom)) esa traversal'ga ochiq. Doim root opsiyasi bilan.

5. Javob bir marta: headersSent

5.1 Haqiqiy xato

Kanon tajribasi — ishlovchi ikki marta res.json() chaqirdi:

text
  ikkinchi res.json() → ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client; res.headersSent = true
/send/ikki → 200 application/json; charset=utf-8  "{\"birinchi\":true}"

Cannot set headers after they are sent to the client — "sarlavhalar mijozga yuborilgandan keyin ularni o'rnatib bo'lmaydi". Mijoz birinchi javobni oldi. Ikkinchisi — serverdagi xato. res.headersSent — true: sarlavhalar ketdi, endi status ham, sarlavha ham o'zgarmaydi.

5.2 Nega bu bo'ladi: return unutilgan

Eng ko'p uchraydigan sabab — res.json() funksiyani to'xtatadi deb o'ylash. Kanon middleware tajribasi buni izda ko'rsatdi:

text
   5:handler (javob)
   5b:res.send() dan keyingi kod ham ishlaydi

res.send() dan keyingi qator ham bajarildi. Demak bunday kod ikki marta javob beradi:

js
// ❌ topilmasa ham ikkinchi res.json ishlaydi
app.get("/vazifalar/:id", async (req, res) => {
  const v = await ombor.ol(id);
  if (!v) res.status(404).json({ xato: "topilmadi" });
  res.json(v);
});
js
// ✅ return — javobdan keyin chiqib ketish
if (!v) return res.status(404).json({ xato: "topilmadi" });
res.json(v);

Kanon uchinchi yo'lni tanladi: xato bo'lsa throw new HttpXato(404, …). throw funksiyani to'xtatadi, xato esa bitta joyda javobga aylanadi.

5.3 Xato ishlovchida headersSent

Javob yarmida (masalan, fayl stream qilinayotganda) xato bo'lsa, status va sarlavhalarni o'zgartirib bo'lmaydi. Kanon xato ishlovchisi buni tekshiradi:

ts
if (res.headersSent) {
  next(xato); // javob yarmida — Express o'zi ulanishni uzadi
  return;
}

Holat 05 dagi node:http versiyasida xuddi shu joyda res.destroy() bor edi.

Tekshirib ko'ring: Log'da ERR_HTTP_HEADERS_SENT chiqyapti, mijoz esa to'g'ri javob olayapti. Bu xato muhimmi?

Javob

Ha. Mijoz birinchi javobni oldi — u to'g'ri bo'lmasligi mumkin (masalan, 404 o'rniga 200 bo'lishi kerak edi yoki aksincha). Ikkinchi javob yozilmagan, lekin uni tayyorlagan kod ishladi — bazaga ikkinchi yozuv, ikkinchi email bo'lishi mumkin. Sababi — return yoki throw yetishmaydi.

6. res.locals — so'rov davomidagi ma'lumot

res.locals — bitta so'rov uchun bo'sh obyekt. Middleware unga yozadi, keyingilari o'qiydi. So'rov tugashi bilan yo'qoladi. Biz sinadik: birinchi middleware res.locals.boshlandi = 1700 yozdi, ishlovchi res.json({ locals: res.locals }) qaytardi → {"locals":{"boshlandi":1700}}.

Qachon ishlatiladi: tekshirilgan query (Express 5 da req.query ni qayta yozib bo'lmaydi — req darsi), autentifikatsiyadan o'tgan foydalanuvchi, so'rov boshlangan vaqt. TypeScript'da req ga o'z xususiyatingizni qo'shish (req.sorovId) ham mumkin — Express + TypeScript darsida.

7. Hujumchi nigohi

Muammo Oqibat Himoya
res.send(foydalanuvchiMatni) text/html — XSS res.json() yoki res.type("text/plain")
Sukut xato ishlovchi stack trace, server yo'llari o'z JSON xato ishlovchingiz; NODE_ENV=production
sendFile(join(papka, nom)) traversal sendFile(nom, { root })
res.redirect(req.query.qaytish) open redirect ruxsat etilgan yo'llar ro'yxati
X-Powered-By texnologiya oshkor app.disable("x-powered-by")

To'rtinchi qator: kirishdan keyin "qaytish" sahifasiga yo'naltirish keng tarqalgan. ?qaytish=https://yomon.example.net — foydalanuvchi sizning saytingizdagi havolani bosib, hujumchi saytiga tushadi. Faqat / bilan boshlanadigan va // bilan boshlanmaydigan ichki yo'llarga ruxsat bering.

8. API qadami: javoblar Express usulida (holat 13, 3-qism)

Hali commit qilmang. Bugun kod o'zgarmaydi. Express'ga kirish darsida ko'chirgan ilova.ts da eski json(res, …) yordamchisi o'rnida endi res metodlari turibdi:

ts
.post(jsonKerak, (req, res) => {
  const t = yangiVazifaniTekshir(req.body);
  if (!t.ok) throw new HttpXato(422, t.xato);
  const v = ombor.yarat(t.qiymat);
  res.status(201).location(`/vazifalar/${String(v.id)}`).json(v);
})
ts
.delete((req, res) => {
  const id = idniOl(req.params.id);
  if (!ombor.ochir(id)) throw topilmadi(id);
  res.sendStatus(204);
})

Uch detal:

  • Location — hozircha qattiq yozilgan /vazifalar/…. Router darsida u ${req.baseUrl}/… ga aylanadi: router boshqa yo'lga (/v1/vazifalar) ko'chsa, kod o'zgarmaydi.
  • Xatolar — throw new HttpXato(...), res.status(...).json(...) emas. Ikki marta javob tuzog'i yo'q.
  • 405 uchun res.set("Allow", allow) keyin throw — Allow sarlavhasi xato javobiga ham tushadi.

Kanon jonli tekshiruvidan (holat 13). Sarlavhalar tartibiga qarang:

text
HTTP/1.1 201 Created
Location: /vazifalar/1
Content-Type: application/json; charset=utf-8
Content-Length: 144
ETag: W/"90-cLr/mALQjIBtdTNRnFKGbGZTkXU"
Connection: keep-alive
Keep-Alive: timeout=65

Nima bo'ldi? Holat 07 bilan farq: ETag paydo bo'ldi (Express), sarlavhalar tartibi o'zgardi (Location birinchi — u res.location() bilan oldinroq qo'yildi). Tana va status — bir xil, testlar o'tdi. Bugungi kesimda ham npm run check yashil.

9. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
ERR_HTTP_HEADERS_SENT ikki marta javob, return yo'q return res... yoki throw
So'rov osilib qoladi res.status() dan keyin yuborish yo'q sendStatus yoki .json()
JSON o'rniga HTML res.send(satr) res.json()
TypeError: path must be absolute or specify root to res.sendFile nisbiy yo'l, root siz { root } opsiyasi
Javobda stack trace xato ushlanmagan o'z xato ishlovchi
maxAge: 60 — cookie darhol o'chadi millisekund kutiladi 60_000

path must be absolute or specify root to res.sendFile — "yo'l mutlaq bo'lishi yoki root ko'rsatilishi kerak". Bu Express'ning sizni traversal'dan ogohlantirishi.

10. Mashqlar

Yechimlar kurs/mashqlar/25/11-res/ da.

1-mashq (oson): to'ldiring

  • res.send("salom") beradigan Content-Type — text/
  • Tanasiz 204 javob — res.(204)
  • Javob yuborilganini bildiradigan xususiyat — res.
  • Yuklab olishga majburlovchi sarlavha — Content-: attachment
  • Bir so'rov davomida middleware'lar ma'lumot almashadigan obyekt — res.
Yechim
  • html — shuning uchun API'da res.json().
  • sendStatus — status(204) yolg'iz javob yubormaydi.
  • headersSent — true bo'lsa, sarlavha o'zgartirib bo'lmaydi.
  • Disposition — res.download() qo'yadi.
  • locals — so'rov tugashi bilan yo'qoladi.

2-mashq (o'rta): res.send qoidasi

sendTuri(qiymat) toza funksiyasini yozing: Express'ning res.send tanlovini takrorlasin. Satr → "text/html; charset=utf-8", Uint8Array (Buffer ham shu) → "application/octet-stream", null yoki obyekt → "application/json; charset=utf-8", undefined → null (tana yo'q). Eslatma: instanceof — prototip va instanceof; brauzerda Buffer yo'q, new TextEncoder().encode("bayt") Uint8Array beradi.

Yechim
js
function sendTuri(qiymat) {
  if (qiymat === undefined) return null;
  if (typeof qiymat === "string") return "text/html; charset=utf-8";
  if (qiymat instanceof Uint8Array) return "application/octet-stream";
  return "application/json; charset=utf-8";
}

const baytlar = new TextEncoder().encode("bayt");
const royxat = ["salom", baytlar, { a: 1 }, [1, 2], null, undefined];
for (const q of royxat) {
  const nomi = q instanceof Uint8Array ? "Uint8Array"
    : JSON.stringify(q);
  console.log(String(nomi).padEnd(10), sendTuri(q));
}

Konsolda:

text
"salom"    text/html; charset=utf-8
Uint8Array application/octet-stream
{"a":1}    application/json; charset=utf-8
[1,2]      application/json; charset=utf-8
null       application/json; charset=utf-8
undefined  null

Uch qator kanondagi Express chiqishi bilan mos: satr — HTML, Buffer — octet-stream, obyekt — JSON.

3-mashq (qiyin): xavfsiz hujjat berish

Express 5.3.0 bilan GET /hujjat/:nom yozing: hujjatlar/ papkadan sendFile(nom, { root }). Callback'da xatoni ushlang: headersSent bo'lsa — next(xato); status 403 bo'lsa — 403, aks holda 404; ikkalasida ham bir xil JSON {"xato":"hujjat topilmadi"} (traversal urinishini oshkor qilmaslik uchun matn bir xil). menyu.txt, yoq.txt va ..%2fyechim.mjs bilan sinang.

Yechim
js
import express from "express";
import { mkdir, writeFile } from "node:fs/promises";
import { resolve } from "node:path";

await mkdir("hujjatlar", { recursive: true });
await writeFile("hujjatlar/menyu.txt", "osh 35000\n");
const ILDIZ = resolve("hujjatlar");

const app = express();
app.get("/hujjat/:nom", (req, res, next) => {
  res.sendFile(req.params.nom, { root: ILDIZ }, (xato) => {
    if (!xato) return; // fayl yuborildi
    if (res.headersSent) return next(xato); // yarmida uzildi
    const status = xato.status === 403 ? 403 : 404;
    res.status(status).json({ xato: "hujjat topilmadi" });
  });
});

const server = app.listen(0, "127.0.0.1");
await new Promise((ok) => server.once("listening", ok));
const a = `http://127.0.0.1:${server.address().port}/hujjat/`;
for (const nom of ["menyu.txt", "yoq.txt", "..%2fyechim.mjs"]) {
  const r = await fetch(a + nom);
  console.log(nom.padEnd(16), r.status, (await r.text()).trim());
}
server.closeAllConnections();
server.close();

Konsolda:

text
menyu.txt        200 osh 35000
yoq.txt          404 {"xato":"hujjat topilmadi"}
..%2fyechim.mjs  403 {"xato":"hujjat topilmadi"}

..%2f URL'da kodlangan, Express uni req.params.nom ga ../yechim.mjs qilib dekodlaydi. send kutubxonasi .. ni ko'rib 403 qaytaradi. Stack trace yo'q — xatoni o'zimiz ushladik.

4-mashq: API qadami

Tajriba: ilova.ts dagi DELETE ishlovchisida res.sendStatus(204) ni vaqtincha res.status(204).json({ ok: true }) ga almashtiring. npm test ni ishga tushiring, keyin bitta vazifani yaratib o'chiradigan fetch bilan javobning statusi, content-type, content-length va tanasini chiqaring. Nima ko'rdingiz va testlar buni sezdimi? Asl holiga qaytaring. Commit qilmang.

Yechim

Biz ishga tushirdik: testlar 7/7 o'tdi, fetch esa 204 null null "" ko'rsatdi — tana ham, Content-Type ham, Content-Length ham yo'q. 204 javobida tana bo'lishi mumkin emas, Express va Node uni jim tashlab yubordi. Mijoz { ok: true } ni hech qachon ko'rmaydi. Testlar faqat statusni tekshirgani uchun bu sezilmadi. Saboq: tana kerak bo'lsa — 200, kerak bo'lmasa — sendStatus(204).

11. Real ishda

  • API'larda — 90 % javob res.status(...).json(...); qolgani sendStatus(204), redirect (OAuth qaytishlari), download (eksport, hisobot).
  • Kod review'da — return siz res.json va res.send(satr) eng ko'p topiladigan xatolar.
  • Prodakshnda — stack trace oqishi xavfsizlik auditida "Information Exposure" sifatida belgilanadi.
  • Intervyu: "res.send va res.json farqi?", "ERR_HTTP_HEADERS_SENT sababi?", "res.locals nima uchun?".

Xulosa

  • res.status(), set(), location() — faqat yozib qo'yadi va res qaytaradi; json(), send(), sendStatus(), end() — yuboradi.
  • res.send(satr) — text/html; API'da res.json().
  • Javob — bir marta; res.json() funksiyani to'xtatmaydi: return yoki throw. Ikkinchi urinish — ERR_HTTP_HEADERS_SENT.
  • sendFile/download — faqat { root } bilan; xatoni callback yoki o'z xato ishlovchingizda ushlang, aks holda stack trace oqadi.
  • res.cookie — maxAge millisekundda; res.locals — so'rov ichidagi ma'lumot.

Keyingi dars: Middleware va request lifecycle — (req, res, next), app.use, tartib qoidasi, next('route'), xato middleware va 405.

Manbalar

  • Express 5.x API — res.status, json, send, sendStatus, redirect, location, sendFile, download, cookie, locals, headersSent: https://expressjs.com/en/5x/api.html#res
  • Express — "Error handling" (sukut xato ishlovchi va NODE_ENV): https://expressjs.com/en/guide/error-handling.html
  • Kanon: req/res va middleware tajribalari (Express 5.3.0, Node 24.21.0), holat 13 jonli curl (201, 204 ETag). sendFile/download/cookie/locals va 403 stack trace — biz ishga tushirdik (yo'llar qisqartirilgan).
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Express res obyekti: res.status, res.json, res.send, sendStatus, redirect, sendFile va headersSent — IlmHamroh