Простейший сервер на модуле 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/POST | res.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).