БэкендJavaScript

Первый REST API на Node.js и Express: GET, POST и JSON

Собираем небольшой Express 5 API для задач: получаем список, создаём запись, проверяем JSON, возвращаем статусы 200, 201 и 400.

Кодик

Автор

7 мин чтения

Express связывает HTTP-метод и путь с функцией, которая читает запрос и формирует JSON-ответ. Соберём API задач с GET /tasks и POST /tasks, проверим пустой title и увидим разницу между статусами 200, 201 и 400. База пока не нужна: данные живут в массиве, чтобы маршрут запроса был виден целиком.

Новичок часто видит route, middleware и status как отдельные термины. Один сервер показывает их в реальном порядке от входящего запроса до ответа. В этой статье вы соберёте локальный REST API с двумя маршрутами. Финальный результат можно проверить без догадок: curl получает исходный список, POST создаёт задачу с новым id, а пустой title возвращает JSON-ошибку и код 400.

1GET

Читает список и не меняет состояние сервера.

2POST

Принимает JSON, проверяет title и добавляет новую задачу.

3Response

Возвращает статус, заголовок Content-Type и сериализованное тело.

Как HTTP-запрос попадает в Express

Клиент отправляет метод, URL, заголовки и тело. Express вызывает express.json до маршрутов, затем выбирает app.get или app.post по методу и path. Handler читает req.body, меняет массив и завершает запрос через res.json или res.status(...).json. Для Express API держите этапы раздельно: ввод, проверка, основное действие и вывод. Такой маршрут позволяет остановиться в конкретной точке, увидеть фактические данные и исправить одну причину вместо случайной перестановки строк.

ЭтапДействиеПроверяемый результат
ПриёмNode.js получает HTTP-запросЕсть method и URL
Middlewareexpress.json разбирает bodyreq.body является объектом
RouteExpress сопоставляет метод и pathВыбран один handler
ОтветHandler задаёт status и JSONКлиент получает завершённый response

Маршрут является парой метод + путь, поэтому GET /tasks и POST /tasks могут существовать одновременно. У Express API каждый этап оставляет наблюдаемый след, поэтому следующий шаг начинается только после проверки предыдущего.

Путь HTTP-запроса через Express
От входных данных до видимого результата. Метод и путь выбирают ровно один handler

Не доверяйте req.body только потому, что это JSON. Парсер проверяет синтаксис, но не смысл. Поле title всё равно может отсутствовать, быть числом или состоять из пробелов.

Пишем GET и POST маршруты

Создайте каталог, выполните npm init -y и npm install express. Добавьте в package.json поле "type": "module", сохраните server.js и запустите node server.js. Для автоматического перезапуска можно использовать node --watch server.js. Проверяйте запросы во втором терминале через curl.

import express from "express";

const app = express();
app.use(express.json({ limit: "20kb" }));

const tasks = [
  { id: 1, title: "Read Express docs", done: false },
];

app.get("/tasks", (request, response) => {
  response.json({ items: tasks, count: tasks.length });
});

app.post("/tasks", (request, response) => {
  const title = request.body?.title;
  if (typeof title !== "string" || title.trim().length < 2) {
    return response.status(400).json({
      error: "title must contain at least 2 characters",
    });
  }

  const task = {
    id: tasks.at(-1)?.id + 1 || 1,
    title: title.trim(),
    done: false,
  };
  tasks.push(task);
  return response.status(201).json(task);
});

app.use((request, response) => {
  response.status(404).json({ error: "route not found" });
});

app.listen(3000, () => {
  console.log("API: http://localhost:3000");
});
Что должно произойти после запуска
  • GET /tasks отвечает кодом 200 и массивом items.
  • POST /tasks с title отвечает 201 и созданным объектом.
  • Пустой title отвечает 400 без изменения массива.
  • Неизвестный путь отвечает JSON с кодом 404.

return перед error-response не обязателен для Express, но он явно останавливает handler и защищает от второго ответа. Пример Express API специально ограничен одним пользовательским сценарием, чтобы назначение каждой строки оставалось видимым.

Случайный handler и явный контракт API
Что отличает устойчивый проект от случайного запуска. Статус является частью ответа

Зачем нужны middleware и коды ответа

express.json является middleware: он выполняется до подходящего маршрута и вызывает next после разбора тела. Если Content-Type не application/json, req.body может остаться undefined. res.json сериализует объект и задаёт тип ответа. Код 201 сообщает, что ресурс создан, а 400 означает ошибку входных данных. Массив существует только в памяти процесса, поэтому перезапуск сервера удаляет новые задачи. Это нормально для лаборатории, но не для настоящего хранения.

ЧастьЗа что отвечаетЧто проверить
app.useПодключает middlewareПарсер стоит до маршрутов
app.getОбрабатывает чтениеНе изменяет tasks
app.postСоздаёт ресурсПроверяет body до push
res.statusЗадаёт код HTTP201 и 400 различаются
404 handlerЛовит неизвестные путиСтоит после маршрутов

Query string не является частью route path: /tasks?done=true всё равно попадает в /tasks, а параметр читается через req.query. Для /tasks/:id используется req.params. Асинхронная база добавит await и обработку ошибок, но не меняет контракт маршрута. Не возвращайте stack trace клиенту. В Express 5 отклонённый Promise из async-handler передаётся обработчику ошибок, однако в учебном сервере полезно сначала увидеть синхронный путь. Ограничение body защищает лабораторию от случайно огромного JSON, но не заменяет аутентификацию и rate limit.

Один запрос должен получать один ответ. После res.status(...).json(...) завершайте ветку через return или else. Иначе код может дойти до второго res.json и вызвать ошибку headers already sent.

Проверяем API через curl и неверный JSON

Запустите сервер и выполните GET. Создайте задачу через curl -X POST http://localhost:3000/tasks -H "Content-Type: application/json" -d "{"title":"Write tests"}". Повторите GET. Затем отправьте пустую строку, число и сломанный JSON. Добавьте PATCH /tasks/:id, который меняет done, но сначала проверяет числовой id и наличие задачи. Верните 404, если id не найден. После этого вынесите проверку title в функцию и протестируйте её отдельно.

Проверка своими руками
  1. Получите начальный список через GET.
  2. Создайте задачу и проверьте статус 201.
  3. Отправьте пустой title и получите 400.
  4. Откройте неизвестный путь и получите 404.
  5. Добавьте PATCH для поля done.
  6. Перезапустите сервер и объясните потерю данных.
Готово, если выполняются все пункты
  • GET не меняет массив.
  • POST валидирует JSON.
  • Коды ответа различаются.
  • 404 возвращается в одном формате.

Рабочий API определяется не количеством маршрутов, а предсказуемым контрактом для успеха и ошибки. После этой проверки измените одно правило Express API и заранее запишите ожидаемый результат. Так копирование превращается в понимание.

Четыре проверки REST-маршрутов
Четыре проверки перед следующим шагом. Ошибки проверяются так же, как успех

Что добавить перед настоящим продом

Перед продом замените массив базой, добавьте схему валидации, единый error-handler, журнал запросов и тесты. Аутентификацию подключайте до приватных маршрутов. CORS нужен только когда браузерный клиент находится на другом origin, он не защищает сервер от curl. Настройте переменную PORT вместо жёсткого 3000 и корректное завершение процесса. Документируйте пример request и response для каждого статуса, чтобы фронтенд не угадывал форму ошибки.

Как изучить тему в Кодике

Повторите объекты, массивы, функции и условия JavaScript, затем наложите на них HTTP-методы. В Кодике сначала восстановите чистую логику без фреймворка, затем верните библиотеку и интерфейс Express API.

ШагЧто разобратьМини-проверка
1Объекты и JSONСериализовать одну task
2ФункцииНаписать handler из двух аргументов
3МассивыДобавить task и посчитать count
4УсловияОтклонить пустой title
5HTTPРазвести 200, 201, 400 и 404

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

Забыли express.json

req.body не будет разобран для application/json.

Всегда возвращают 200

Используйте 201 для создания и 400 для неверного ввода.

Проверяют только truthy

Строка из пробелов truthy, поэтому применяйте trim и длину.

Считают массив базой

После перезапуска память очистится, это часть ограничения примера.

Сверяйтесь с первичной документацией. Команды и ограничения примера проверены по официальному руководству Express 5 по routing. Если версия инструмента изменилась, официальный источник важнее старого скриншота.

Что получится в итоге

Готовый результат проекта: Первый REST API на Node.js и Express: GET, POST и JSON
Два маршрута возвращают единый JSON-формат, различают успешное чтение, создание, неверные данные и неизвестный адрес.

Короткие ответы
Что делает express.json?

express.json разбирает JSON-тело запроса и записывает объект в req.body до маршрута.

Чем GET /tasks отличается от POST /tasks?

GET читает список, а POST принимает данные и создаёт новую задачу.

Когда Express API возвращает 201?

Код 201 возвращается после успешного создания нового ресурса.

Как понять, что учебный проект Express API действительно работает?

Проверьте основной сценарий Express API, неверный ввод, повторный запуск и один граничный случай. Затем объясните путь данных своими словами.

Можно ли начать с готового кода Express API из статьи?

Да. Сначала добейтесь результата Express API, затем измените одно правило и восстановите ключевой файл без копирования.

Добавьте фронтенд только после ясного контракта

JavaScript закрепите в курсе JavaScript, а серверные принципы в профессии Backend. Клиентский запрос разберите в статье про Fetch API.

Сравните обычные маршруты с WebSocket-чатом и подключение данных с Supabase Auth.