Можно ли передавать идентификатор (id) в теле POST-запроса при создании ресурса?

«Можно ли передавать идентификатор (id) в теле POST-запроса при создании ресурса?» — вопрос из категории Сети, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Технически — да, но с точки зрения RESTful-архитектуры и семантики HTTP — это противоречивая практика.

Стандартный подход (REST):

  • Метод POST на коллекцию (например, /api/users) предназначен для создания нового ресурса, идентификатор которого должен быть сгенерирован на стороне сервера (часто в БД). Клиент не должен знать или указывать этот id заранее.
  • Успешный ответ 201 Created обычно содержит заголовок Location с URL нового ресурса (например, /api/users/123) и может включать созданный объект в теле.

Пример на Express.js:

app.post('/api/users', async (req, res) => {
  const userData = req.body; // { name: 'Alice', email: 'alice@example.com' }
  // id НЕ ожидается в userData
  const newUser = await db.users.create(userData); // Сервер генерирует id
  res.status(201).location(`/api/users/${newUser.id}`).json(newUser);
});

Когда передача id в POST может иметь смысл (но лучше избегать):

  1. Импорт данных: При массовом импорте существующих данных из другой системы, где id нужно сохранить.
  2. Специфичная бизнес-логика: Если идентификатор является не техническим ключом БД, а частью бизнес-данных (например, артикул товара, который задает клиент).

Альтернативы:

  • Для операций, где клиент определяет ключ ресурса, более семантически верным является метод PUT на конкретный URL (например, PUT /api/users/alices-article-number). PUT идемпотентен и означает «создать или полностью заменить ресурс по данному идентификатору».

В моих проектах на Node.js я строго следую принципам REST: POST для создания без указания id, PUT/PATCH для обновления по известному id. Это делает API предсказуемым и понятным для всех разработчиков.