REST API на Node.js без Express: создаём с нуля

5 минут чтения
Средний рейтинг статьи — 4.9

Большинство разработчиков используют Express или Fastify для создания API на Node.js. Но важно понимать, как всё устроено «под капотом». В этом туториале мы создадим минимальный REST API на чистом Node.js, без сторонних фреймворков.

Что мы сделаем

Соберём простой, но рабочий REST API на чистом Node.js — без Express и других фреймворков. С объяснением, как обрабатывать запросы, читать JSON, отвечать данными и не сойти с ума.

  • HTTP-сервер на Node.js
  • Обработка маршрутов GET, POST, PUT, DELETE
  • Парсинг тела запроса (JSON)
  • Простейший router
  • Возврат JSON-ответов и корректных заголовков

Структура проекта

Минимальная структура папок и файлов, необходимая для запуска проекта. Вот так будет выглядеть наш проект — ничего лишнего:

rest-api-nodejs/
├── index.js
└── data.json

Шаг 1. Создаём HTTP-сервер

Здесь мы инициализируем базовый HTTP-сервер с помощью встроенного модуля http, реализуем базовую маршрутизацию.

// index.js
const http = require('http');
const { parse } = require('url');
 
const PORT = 3000;
 
const server = http.createServer(async (req, res) => {
  const parsedUrl = parse(req.url, true);
  const method = req.method;
  const pathname = parsedUrl.pathname;
 
  // Заголовки по умолчанию
  res.setHeader('Content-Type', 'application/json');
 
  // Простая маршрутизация
  if (method === 'GET' && pathname === '/api/items') {
    return getItems(req, res);
  } else if (method === 'POST' && pathname === '/api/items') {
    return createItem(req, res);
  } else if (method === 'PUT' && pathname.startsWith('/api/items/')) {
    return updateItem(req, res);
  } else if (method === 'DELETE' && pathname.startsWith('/api/items/')) {
    return deleteItem(req, res);
  }
 
  res.statusCode = 404;
  res.end(JSON.stringify({ message: 'Not found' }));
});
 
server.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

Шаг 2. Заглушка для хранения данных

Для простоты будем использовать массив в памяти как временное хранилище вместо базы данных.

// Простейшая in-memory база
let items = [
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
];

Шаг 3. Обработчики маршрутов

Теперь научим сервер понимать, что от него хотят. Реализуем все основные действия: показать список, добавить элемент, обновить и удалить — то есть полный набор CRUD-операций.

Получение всех элементов

Функция возвращает список всех элементов из массива items.

function getItems(req, res) {
  res.statusCode = 200;
  res.end(JSON.stringify(items));
}

Создание нового элемента

Метод читает тело запроса, парсит его как JSON и добавляет новый элемент в массив.

function createItem(req, res) {
  let body = '';
 
  req.on('data', chunk => {
    body += chunk.toString();
  });
 
  req.on('end', () => {
    try {
      const parsed = JSON.parse(body);
      const newItem = {
        id: Date.now(),
        name: parsed.name || 'Unnamed',
      };
      items.push(newItem);
      res.statusCode = 201;
      res.end(JSON.stringify(newItem));
    } catch (e) {
      res.statusCode = 400;
      res.end(JSON.stringify({ message: 'Invalid JSON' }));
    }
  });
}

Обновление элемента

Ищет элемент по ID и обновляет его имя, если элемент найден.

function updateItem(req, res) {
  const id = parseInt(req.url.split('/').pop());
  let body = '';
 
  req.on('data', chunk => {
    body += chunk.toString();
  });
 
  req.on('end', () => {
    try {
      const parsed = JSON.parse(body);
      const item = items.find(i => i.id === id);
      if (!item) {
        res.statusCode = 404;
        return res.end(JSON.stringify({ message: 'Item not found' }));
      }
      item.name = parsed.name || item.name;
      res.end(JSON.stringify(item));
    } catch (e) {
      res.statusCode = 400;
      res.end(JSON.stringify({ message: 'Invalid JSON' }));
    }
  });
}

Удаление элемента

Функция удаляет элемент из массива по ID, если он найден.

function deleteItem(req, res) {
  const id = parseInt(req.url.split('/').pop());
  const index = items.findIndex(i => i.id === id);
 
  if (index === -1) {
    res.statusCode = 404;
    return res.end(JSON.stringify({ message: 'Item not found' }));
  }
 
  items.splice(index, 1);
  res.statusCode = 204;
  res.end();
}

Тестируем API

Пора проверить, что всё реально работает. Вот примеры curl-запросов — можно запускать прямо из терминала.

curl http://localhost:3000/api/items
curl -X POST -d '{"name": "New Item"}' -H "Content-Type: application/json" http://localhost:3000/api/items

Вывод

Мы создали простой, но полностью рабочий REST API без использования Express. Это отличный способ глубже понять, как работает Node.js, и что делает за вас Express «из коробки».

Если хочется пойти дальше: можно добавить поддержку CORS, валидацию данных, логирование, подключить базу вместо массива и разнести код по файлам.

5 минут чтения
Средний рейтинг статьи — 4.9

Настроить мониторинг за 30 секунд

Надежные оповещения о даунтаймах. Без ложных срабатываний