Отличия POST, PUT и PATCH
Короткая модель
| Метод | Кто выбирает URI | Смысл | Идемпотентность |
|---|---|---|---|
| POST | обычно сервер | обработать representation или создать subordinate resource | нет по умолчанию |
| PUT | обычно клиент знает URI | полностью заменить representation ресурса | да |
| PATCH | URI уже известен | применить частичное изменение | зависит от patch document |
POST
POST /orders HTTP/1.1
Content-Type: application/json
Idempotency-Key: request-123
{"productId":7,"quantity":2}Успех создания: 201 Created и Location: /orders/42. Если клиент повторяет POST после timeout, idempotency key позволяет серверу вернуть результат первой операции вместо дубликата. Это прикладной контракт, не автоматическое свойство HTTP.
PUT
PUT /profiles/42 HTTP/1.1
Content-Type: application/json
{"name":"Ada","timezone":"UTC"}PUT обычно передаёт полное новое представление. Повтор оставляет то же состояние. Неуказанные поля при replacement могут сброситься — контракт должен сказать это явно.
PATCH
Merge Patch:
PATCH /profiles/42 HTTP/1.1
Content-Type: application/merge-patch+json
{"timezone":"Europe/Moscow"}Операция “установить timezone” может быть идемпотентной. Операция “увеличить balance на 10” — нет. Поэтому PATCH как метод не гарантирует идемпотентность. JSON Patch и Merge Patch имеют разную семантику; просто application/json оставляет формат неясным.
Конкурентность
Для PUT/PATCH полезен optimistic lock:
If-Match: "version-7"При несовпадении версии сервер возвращает 412 Precondition Failed или договорной 409 Conflict, не затирая изменение другого клиента.
Типичные сбои
- Использовать PUT как частичный update, но не описать судьбу отсутствующих полей.
- Автоматически retry POST без idempotency key.
- Считать любой PATCH идемпотентным.
- Возвращать
201при обычном обновлении существующего ресурса без создания. - Не различать отсутствующее поле и явный
null.
Вопросы для собеседования
Почему PUT идемпотентен? Повтор полной установки representation ведёт к тому же целевому состоянию.
Можно ли сделать POST идемпотентным? Да, прикладным ключом идемпотентности и хранением результата.
PATCH всегда частичный PUT? Нет, он применяет patch document с собственной семантикой.
Как не потерять параллельное обновление? ETag/version и условный request.
См. REST, Версии протокола HTTP.