JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Написание и разбор кода простого сервера

Написание и разбор кода простого сервера

Модуль 4: Node.js, Next.js и Angular
4 уровень , 4 лекция
Открыта

1. Минимальный сервер

Мы напишем с нуля простой HTTP-сервер на Node.js, который:

  • Принимает входящие запросы на разные адреса (роуты)
  • Отвечает разным текстом в зависимости от URL
  • Корректно устанавливает HTTP-заголовки и коды ответа
  • Умеет отдавать простой HTML и JSON
  • Не падает, если пользователь попросил несуществующую страницу

Всё это — база, на которой строятся любые сайты и API. И, поверьте, даже такие простые серверы иногда используются в продакшене (например, для моков, тестов, или микросервисов).

Что мы будем делать?

Давайте начнём с самого минималистичного сервера. Для этого нам понадобится модуль http, который уже встроен в Node.js, так что ничего дополнительно устанавливать не нужно.

Создайте файл server.js и напишите следующее:

// Импортируем модуль http
const http = require('http');

// Создаём сервер
const server = http.createServer((req, res) => {
  // req — объект запроса (что пришло от клиента)
  // res — объект ответа (что мы отправим клиенту)
  res.statusCode = 200; // Устанавливаем HTTP-статус 200 (ОК)
  res.setHeader('Content-Type', 'text/plain'); // Говорим браузеру, что это обычный текст
  res.end('Привет, мир! Мой первый сервер на Node.js.');
});

// Запускаем сервер на порту 3000
server.listen(3000, () => {
  console.log('Сервер запущен на http://localhost:3000');
});

Запустите этот файл командой:

node server.js

Откройте браузер и перейдите по адресу http://localhost:3000 — вы увидите заветное "Привет, мир!".

Как это работает?

  • http.createServer создаёт сервер и принимает функцию-обработчик, которая вызывается при каждом запросе.
  • Внутри обработчика мы формируем ответ: устанавливаем статус, заголовки, и отправляем данные методом res.end().
  • server.listen() запускает сервер и начинает слушать указанный порт.

2. Разбираем код по частям

Импорт модуля http

const http = require('http');

Node.js использует систему модулей CommonJS, поэтому для подключения стандартного модуля используем require. Модуль http даёт всё необходимое для работы с HTTP-протоколом.

Создание сервера

const server = http.createServer((req, res) => {
  // ...
});

Здесь мы создаём сервер и сразу передаём функцию-обработчик. Эта функция будет вызвана каждый раз, когда к серверу кто-то обратится (например, откроет страницу в браузере или отправит запрос с Postman).

Объекты req и res

  • req (request) — содержит всю информацию о запросе: адрес, метод (GET, POST и т.д.), заголовки, тело запроса.
  • res (response) — через него мы формируем и отправляем ответ клиенту: можем задать статус, заголовки, тело ответа.

Установка статуса и заголовков

res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
  • statusCode — HTTP-статус (200 — всё хорошо, 404 — не найдено, 500 — ошибка сервера и т.д.)
  • setHeader — позволяет указать заголовки. В данном случае мы говорим браузеру, что отправляем обычный текст.

Отправка ответа

res.end('Привет, мир!');

Метод end завершает формирование ответа и отправляет его клиенту. Всё, что вы передадите в end, попадёт в браузер (или другой клиент).

3. Добавляем маршрутизацию (роутинг)

Один из самых частых вопросов: как сделать так, чтобы сервер отвечал разным текстом на разные адреса? Например, на / отдавал приветствие, а на /about — рассказывал о себе.

Для этого нам нужно посмотреть на свойство req.url:

const server = http.createServer((req, res) => {
  // req.url — строка с адресом запроса, например "/about"
  if (req.url === '/') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');
    res.end('<h1>Главная страница</h1><p>Добро пожаловать на мой сервер!</p>');
  } else if (req.url === '/about') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');
    res.end('<h1>О сервере</h1><p>Этот сервер написан на Node.js.</p>');
  } else if (req.url === '/api') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'application/json');
    // Отправим JSON как строку
    res.end(JSON.stringify({ message: 'Это API', status: 'ok' }));
  } else {
    res.statusCode = 404;
    res.setHeader('Content-Type', 'text/html');
    res.end('<h1>404 - Не найдено</h1><p>Такой страницы нет :(</p>');
  }
});

Теперь сервер умеет:

  • Отвечать разным HTML на / и /about
  • Отдавать JSON на /api
  • Отдавать ошибку 404 на любые другие адреса

4. Пример полноценного сервера (пошагово)

Давайте напишем весь код сервера с комментариями:

const http = require('http');

// 1. Создаём сервер
const server = http.createServer((req, res) => {
  // 2. Логируем запросы для наглядности
  console.log(`${req.method} ${req.url}`);

  // 3. Простейший роутинг
  if (req.url === '/' && req.method === 'GET') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');
    res.end(`
      <h1>Главная страница</h1>
      <p>Добро пожаловать! <a href="/about">О сервере</a> | <a href="/api">API</a></p>
    `);
  } else if (req.url === '/about' && req.method === 'GET') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');
    res.end(`
      <h1>О сервере</h1>
      <p>Этот сервер написан на Node.js.<br>
      <a href="/">На главную</a></p>
    `);
  } else if (req.url === '/api' && req.method === 'GET') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'application/json');
    // Отправим JSON как строку
    res.end(JSON.stringify({
      success: true,
      message: 'Привет из API!',
      time: new Date().toISOString()
    }));
  } else {
    // 4. Если адрес не найден — 404
    res.statusCode = 404;
    res.setHeader('Content-Type', 'text/html');
    res.end(`
      <h1>404 — Не найдено</h1>
      <p>Такой страницы нет! <a href="/">На главную</a></p>
    `);
  }
});

// 5. Запускаем сервер на порту 3000
const PORT = 3000;
server.listen(PORT, () => {
  console.log(`Сервер запущен на http://localhost:${PORT}`);
});

Что происходит по шагам?

  1. Импортируем модуль http.
  2. Создаём сервер с обработчиком запросов.
  3. Логируем каждый запрос (для отладки и понимания, что происходит).
  4. Проверяем URL и метод запроса — отвечаем разным содержимым.
  5. Для неизвестных адресов возвращаем ошибку 404.
  6. Запускаем сервер на порту 3000.

5. Как протестировать сервер

Откройте браузер и попробуйте адреса:

Можно использовать curl или Postman для проверки (особенно удобно для API):

curl http://localhost:3000/api

В консоли вы увидите логи всех входящих запросов.

6. Добавляем обработку POST-запросов (чуть сложнее)

Давайте научим сервер принимать данные, отправленные методом POST (например, с формы или из API-клиента). Для этого нам нужно "собирать" тело запроса вручную — Node.js не делает этого автоматически (в отличие от Express).

Добавим новый роут /echo, который повторяет (эхом) всё, что вы ему отправите:

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.url === '/echo' && req.method === 'POST') {
    let body = '';
    // Слушаем поступающие данные (частями)
    req.on('data', chunk => {
      body += chunk;
    });
    // Когда все данные получены
    req.on('end', () => {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'application/json');
      res.end(JSON.stringify({
        received: body
      }));
    });
  } else {
    res.statusCode = 404;
    res.end('Not found');
  }
});

server.listen(3000, () => {
  console.log('Сервер на порту 3000');
});

Теперь можно отправить POST-запрос через curl:

curl -X POST -d "hello=world" http://localhost:3000/echo

Ответ будет:

{"received":"hello=world"}

Зачем это всё?

  • Вы учитесь работать с HTTP-протоколом "на низком уровне" — это мощное знание, пусть даже большинство разработчиков пользуются фреймворками типа Express.
  • Понимаете, как обрабатываются разные методы запросов (GET, POST).
  • Видите, как сервер "собирает" тело запроса по частям (streaming!), что важно для больших данных.

7. Типичные ошибки при написании простого сервера

Ошибка №1: забыли вызвать res.end()

Если не вызвать res.end(), браузер будет ждать ответа вечно — и вы увидите "вечную загрузку". Всегда завершайте ответ!

Ошибка №2: неправильный Content-Type

Если отправляете JSON, но забыли поставить Content-Type: application/json, браузер и клиенты могут не распознать ответ как JSON. Аналогично с HTML.

Ошибка №3: не проверяете метод запроса

Часто пишут только проверку URL, но забывают про метод (GET, POST и др.). В результате сервер может принять не тот тип запроса, что ожидалось.

Ошибка №4: не обрабатываете неизвестные адреса

Если не добавить блок для 404, сервер просто ничего не ответит или вернёт неинформативную ошибку.

Ошибка №5: не логируете ошибки

Если в обработчике возникла ошибка, а вы не вывели её в консоль, будет сложно понять, что пошло не так. Логируйте всё, что кажется подозрительным!

Ошибка №6: забыли перезапустить сервер после изменения кода

Node.js не перезапускает сервер автоматически (если не используете nodemon). После изменений обязательно останавливайте сервер и запускайте снова.

1
Задача
Модуль 4: Node.js, Next.js и Angular, 4 уровень, 4 лекция
Недоступна
Сервер с базовой маршрутизацией
Сервер с базовой маршрутизацией
1
Задача
Модуль 4: Node.js, Next.js и Angular, 4 уровень, 4 лекция
Недоступна
Выдача JSON и обработка POST-запроса
Выдача JSON и обработка POST-запроса
3
Опрос
Создание HTTP-сервера, 4 уровень, 4 лекция
Недоступен
Создание HTTP-сервера
Создание HTTP-сервера
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ