Простейший сервер на модуле http

Веб-сервер без единого внешнего пакета — на встроенном модуле http.

Модуль http — встроенный модуль Node для создания веб-серверов и отправки HTTP-запросов. Это фундамент, на котором построены Express и другие фреймворки.

Сервер в несколько строк

Функция http.createServer создаёт сервер. Ей передают функцию-обработчик, которая вызывается на КАЖДЫЙ входящий запрос. Затем сервер начинает слушать порт методом listen:

const http = require("http");

const server = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
  res.end("Привет от Node-сервера!");
});

server.listen(3000, () => {
  console.log("Сервер слушает http://localhost:3000");
});

Запустите node server.js, откройте в браузере http://localhost:3000 — увидите текст ответа. Сервер не завершается: он висит и ждёт запросов.

Объекты req и res

Обработчик получает два объекта:

req (запрос)res (ответ)
что прислал клиентчто мы отправим обратно
req.url — путьres.writeHead — статус и заголовки
req.method — GET/POSTres.end — тело и завершение
req.headers — заголовкиres.write — кусок ответа

Статус и заголовки

Метод res.writeHead задаёт код статуса (200 — успех, 404 — не найдено) и заголовки. Заголовок Content-Type сообщает браузеру тип содержимого:

// HTML-ответ
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end("<h1>Привет</h1>");

// JSON-ответ
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: true }));

Важно: res.end обязательно нужно вызвать — иначе браузер будет вечно ждать ответ. Это одна из самых частых ошибок новичков: код отработал, а вкладка в браузере «крутится» бесконечно, потому что сервер так и не сообщил, что ответ завершён.

Заголовок Content-Type — не формальность: именно по нему браузер решает, как показать ответ. С text/html он отрисует теги как страницу, с application/json покажет данные, а с text/plain выведет текст как есть. Перепутаете тип — и вместо красивой страницы увидите сырые угловые скобки. Поэтому всегда указывайте тип, подходящий тому, что вы реально отправляете.

Каждый запрос обрабатывается отдельно

Обработчик вызывается заново на каждый запрос. Внутри вы решаете, что ответить, опираясь на req.url и req.method. Логику ответа легко показать на чистом JS:

function handleRequest(url) {
  if (url === "/") return "Главная страница";
  if (url === "/about") return "О нас";
  return "404 — не найдено";
}

console.log(handleRequest("/"));
console.log(handleRequest("/about"));
console.log(handleRequest("/unknown"));

Вывод:

Главная страница
О нас
404 — не найдено

Формируем JSON-ответ

Тело ответа — всегда строка. Объект превращают в строку через JSON.stringify — это чистый JS:

const user = { id: 1, name: "Аня", active: true };

const body = JSON.stringify(user);
console.log("Тело ответа:", body);
console.log("Длина:", body.length);

Вывод:

Тело ответа: {"id":1,"name":"Аня","active":true}
Длина: 35

Итог

  • http.createServer((req, res) => {...}) создаёт сервер.
  • server.listen(порт) начинает слушать запросы.
  • req — данные запроса, res — ответ; res.end обязателен.
  • res.writeHead задаёт статус и заголовки (например, Content-Type).
Проверьте себя
1. Какая функция создаёт HTTP-сервер в Node?
Ahttp.listen
Bhttp.createServer
Chttp.start
Dnew Server()
2. Что обязательно нужно вызвать, чтобы завершить ответ?
Ares.close
Bres.end
Cres.send
Dres.finish
3. Откуда узнать, какой путь запросил клиент?
Ares.url
Breq.url
Creq.path только в Express
Dserver.url
Поддержать проект