Методи REST API: GET, POST, PUT, PATCH і DELETE простими словами

Що робить кожен метод REST API: приклади запитів, коди відповіді, різниця між PUT і PATCH та які запити безпечно повторювати.

Ілюстрація до статті: Методи REST API: GET, POST, PUT, PATCH і DELETE простими словами

Кожен запит до REST API починається з методу — слова перед адресою, яке каже серверу, що ви хочете зробити. Здебільшого вистачає п’яти: GET, POST, PUT, PATCH і DELETE. У статті пояснюємо, що означає кожен метод і які коди відповіді від нього чекати. Також розбираємо два правила, які новачки часто пропускають, — безпечність та ідемпотентність. Від них залежать повторні спроби, кешування і помилки, які важко знайти. Загалом про REST читайте в статті Що таке REST API?.

Коротка шпаргалка

Метод Що робить Тіло запиту Безпечний Ідемпотентний Типовий код успіху
GET Читає ресурс або список Ні Так Так 200 OK
POST Створює ресурс або запускає дію Так Ні Ні 201 Created / 202 Accepted
PUT Повністю замінює ресурс Так Ні Так 200 OK / 204 No Content
PATCH Змінює частину ресурсу Так Ні Не гарантовано 200 OK
DELETE Видаляє ресурс Зазвичай ні Ні Так 204 No Content
HEAD Як GET, але лише заголовки Ні Так Так 200 OK
OPTIONS Дізнатися, які методи дозволені Ні Так Так 204 No Content

У прикладах нижче — уявний API книгарні за адресою https://api.example.com/v1/books.

GET: читання даних

GET запитує представлення ресурсу: GET /v1/books повертає список, а GET /v1/books/42 — одну книжку. Список звужують параметрами запиту, наприклад GET /v1/books?author=orwell&page=2.

GET /v1/books/42 HTTP/1.1
Host: api.example.com
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{"id": 42, "title": "1984", "author": "George Orwell", "price": 9.99}

GET ніколи не повинен змінювати дані. Браузери, проксі та пошукові роботи вважають його нешкідливим: вони можуть завантажувати сторінку наперед, кешувати й повторювати запит. Класична помилка — посилання на зразок GET /books/42/delete: робот або бот попереднього перегляду посилань перейде за ним і видалить книжку.

POST: створення нового

POST надсилає дані в колекцію. Сервер створює новий запис і сам призначає йому ідентифікатор.

POST /v1/books HTTP/1.1
Content-Type: application/json

{"title": "Прекрасний новий світ", "author": "Aldous Huxley", "price": 8.50}

HTTP/1.1 201 Created
Location: /v1/books/43

Заголовок Location показує, де лежить новий ресурс. POST — це ще й універсальний метод для дій, які не вписуються в інші, наприклад POST /v1/orders/7/refund або POST /v1/reports для запуску довгої задачі. На довгу задачу сервер часто відповідає 202 Accepted і посиланням, за яким потім перевіряють її статус.

POST не ідемпотентний: той самий запит двічі зазвичай створює два записи. Тому багато платіжних API та API замовлень приймають заголовок Idempotency-Key. Ви генеруєте унікальне значення для кожної логічної операції. Якщо повторний запит прийде з тим самим ключем, сервер поверне перший результат, а не спише гроші вдруге.

PUT: повна заміна ресурсу

PUT надсилає на адресу ресурсу його повну нову версію. Що надіслали, тим ресурс і стане. Поле, яке ви не вказали, буде очищене або скинуте до значення за замовчуванням.

PUT /v1/books/43 HTTP/1.1
Content-Type: application/json

{"title": "Прекрасний новий світ", "author": "Aldous Huxley", "price": 7.99}

Десять однакових PUT дають той самий стан, що й один. Саме це й означає ідемпотентність. Деякі API дозволяють створювати ресурс через PUT, якщо адресу обирає клієнт, наприклад PUT /v1/settings/theme.

PATCH: зміна окремих полів

PATCH надсилає лише поля, які треба змінити. Це природний вибір для форм, де редагують одне-два значення.

PATCH /v1/books/43 HTTP/1.1
Content-Type: application/merge-patch+json

{"price": 6.99}

У поширеному форматі JSON Merge Patch (RFC 7396) ви перелічуєте поля для зміни, а null видаляє поле. Інший формат, JSON Patch (RFC 6902), надсилає список операцій: add, remove, replace. PATCH не обов’язково ідемпотентний. {"price": 6.99} щоразу дає той самий результат, а «збільшити залишок на 1» — ні.

PUT проти PATCH на одному прикладі

Нехай у книжки 43 є title, author, price і tags. Якщо надіслати PUT лише з {"price": 6.99}, суворий API замінить книжку об’єктом, у якому є тільки ціна. Назва, автор і теги зникнуть. Те саме тіло в PATCH змінить ціну, а решту залишить. Якщо сумніваєтеся, для часткових змін беріть PATCH, а PUT — лише тоді, коли справді надсилаєте весь об’єкт.

DELETE: видалення

DELETE /v1/books/43 HTTP/1.1

HTTP/1.1 204 No Content

Після повторного видалення стан сервера той самий, тому DELETE ідемпотентний. Друга спроба може повернути 404 Not Found, і це нормально: ідемпотентність стосується стану на сервері, а не однакових відповідей. Багато систем роблять «м’яке видалення»: запис лише позначається видаленим, і його можна відновити.

HEAD і OPTIONS

HEAD повертає ті самі заголовки, що й GET, але без тіла. Так можна перевірити, чи існує великий файл і який у нього розмір, не завантажуючи його. OPTIONS браузер надсилає сам як CORS-«preflight» перед деякими запитами на інший домен. Від відповіді сервера, зокрема заголовка Access-Control-Allow-Methods, залежить, чи дозволить браузер справжній запит. Якщо запит працює з командного рядка, але в браузері падає з помилкою CORS, шукайте причину саме в цьому preflight.

Безпечність та ідемпотентність: чому це важливо

  • Безпечні методи (GET, HEAD, OPTIONS) лише читають дані. На це покладаються кеші, пошукові роботи й механізми попереднього завантаження.
  • Ідемпотентні методи (GET, PUT, DELETE і всі безпечні) можна повторювати без зміни результату. Якщо зв’язок обірвався, клієнт може просто повторити запит. Для повтору POST потрібен ключ ідемпотентності або перевірка, що перша спроба справді не пройшла.

Ці правила записані в стандарті HTTP (RFC 9110). Це обіцянки, які дає API, і виконувати їх має код сервера.

Коди відповіді, які ви побачите

  • 200 OK — успіх із тілом відповіді. 201 Created — ресурс створено, його адреса в заголовку Location. 204 No Content — успіх без тіла.
  • 400 Bad Request — запит сформовано неправильно. 422 Unprocessable Content — формат правильний, але дані не пройшли перевірку.
  • 401 Unauthorized — немає облікових даних або вони недійсні. 403 Forbidden — облікові дані дійсні, але на цю дію немає прав. Див. API-ключі та OAuth-токени.
  • 404 Not Found — ресурсу не існує. 405 Method Not Allowed — ця адреса не підтримує метод; які методи працюють, видно в заголовку Allow.
  • 409 Conflict — наприклад, хтось уже змінив ресурс раніше за вас. 412 Precondition Failed — не пройшла перевірка If-Match.
  • 429 Too Many Requests — ви перевищили ліміт запитів. Почекайте стільки, скільки вказано в Retry-After.
  • 5xx — проблема на боці сервера. Для ідемпотентних методів доречно повторювати запит зі зростаючою затримкою.

Як не втратити чужі зміни

Коли двоє людей редагують той самий запис, другий PUT може непомітно перезаписати перший. Добре спроєктовані API повертають у відповіді на GET заголовок ETag — мітку версії. Під час збереження клієнт надсилає її назад у заголовку If-Match. Якщо запис за цей час змінився, сервер відповість 412 і не затре чужу роботу.

Спробуйте самі

Потренуватися можна з curl на публічному тестовому сервісі httpbin.org, який повертає назад усе, що ви надіслали:

curl -i https://httpbin.org/get
curl -i -X POST https://httpbin.org/post -H "Content-Type: application/json" -d '{"title":"Test"}'
curl -i -X PATCH https://httpbin.org/patch -H "Content-Type: application/json" -d '{"price":5}'
curl -i -X DELETE https://httpbin.org/delete

Прапорець -i виводить рядок статусу й заголовки, тож ви побачите коди, описані вище.

Типові помилки

  • Змінювати дані через GET, бо так «простіше перевірити в браузері».
  • Робити часткове оновлення через PUT і випадково стирати поля.
  • Автоматично повторювати POST без ключа ідемпотентності — так з’являються дублікати замовлень і платежів.
  • Повертати 200 з {"error": ...} у тілі: клієнти й моніторинг тоді не відрізнять успіх від збою.
  • Передавати секрети в рядку запиту URL: вони потрапляють у журнали та історію браузера. Їм місце в заголовку Authorization.

Підсумок

GET читає, POST створює, PUT замінює, PATCH змінює частину, DELETE видаляє. Тримайте GET без побічних ефектів. Повторюйте лише ідемпотентні запити, якщо не використовуєте ключі ідемпотентності. Дивіться на код відповіді раніше, ніж на тіло. Ці три звички запобігають більшості проблем з REST, які трапляються на практиці. Яке місце REST посідає серед інших видів API, пояснено в статті Що таке API-сервіси?.