Пошук уроків, статей та іншого контенту
Вбудований модуль http — навіщо його розуміти, навіть якщо в проєкті використовується Express чи NestJS.
Реальні застосунки практично завжди використовують фреймворк (Express, NestJS — окремий курс на платформі) замість вбудованого http-модуля напряму, бо фреймворк додає маршрутизацію, middleware, парсинг тіла запиту з коробки. Але сам фреймворк побудований поверх модуля http — розуміння цього базового рівня допомагає розуміти, що саме роблять middleware й маршрутизатори «під капотом».
import { createServer } from "node:http";
const server = createServer((req, res) => {
console.log(`${req.method} ${req.url}`);
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
res.end("Привіт зі сервера!");
});
server.listen(3000, () => {
console.log("Сервер запущено на http://localhost:3000");
});Колбек createServer викликається на кожен вхідний запит із двома об'єктами: req (IncomingMessage — метод, URL, заголовки, тіло запиту) і res (ServerResponse — Writable-потік, куди пишеться відповідь).
Без фреймворка маршрутизація — це звичайні перевірки req.method і req.url, які швидко стають громіздкими навіть для кількох маршрутів — і саме цю громіздкість автоматизують фреймворки:
const server = createServer((req, res) => {
if (req.method === "GET" && req.url === "/") {
res.writeHead(200);
res.end("Головна сторінка");
} else if (req.method === "GET" && req.url === "/about") {
res.writeHead(200);
res.end("Про нас");
} else {
res.writeHead(404);
res.end("Не знайдено");
}
});req сам є Readable-потоком (стаття про Streams цього ж модуля) — тіло POST-запиту приходить частинами, і без фреймворка його потрібно зібрати самостійно:
function readBody(req) {
return new Promise((resolve, reject) => {
let data = "";
req.on("data", (chunk) => (data += chunk));
req.on("end", () => resolve(data));
req.on("error", reject);
});
}
const server = createServer(async (req, res) => {
if (req.method === "POST" && req.url === "/echo") {
const body = await readBody(req);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ received: body }));
}
});Саме цю ручну роботу (маршрутизація за методом/URL, парсинг тіла запиту, встановлення заголовків) фреймворки на кшталт Express чи NestJS автоматизують і роблять декларативною — знання того, що відбувається на цьому нижчому рівні, допомагає розуміти повідомлення про помилки й нетипові ситуації, коли абстракція фреймворка «протікає».
Забути res.end() — відповідь ніколи не завершиться, і клієнт (браузер, curl) чекатиме, поки не спрацює таймаут з'єднання.
Не обробляти невідповідні маршрути (гілка else) — запит на неіснуючий шлях зависає без відповіді замість чіткого 404.
Писати повноцінний маршрутизатор і middleware-систему з нуля на голому http-модулі для реального проєкту — виправдано для навчання, але для продакшн-коду для цього й існують фреймворки, тестові й перевірені спільнотою.
Вбудований модуль http дає мінімальний, низькорівневий спосіб приймати HTTP-запити й відправляти відповіді — req і res є, відповідно, Readable- і Writable-потоками, а маршрутизація й парсинг тіла запиту виконуються вручну. У реальних проєктах цей рівень майже завжди прихований за фреймворком, але розуміння його корисне для розуміння того, що фреймворк робить «під капотом».