Коди статусу HTTP та їхнє призначення
Коди статусу HTTP та їхнє призначення
🎯 Мета розділу
- Опанувати класифікацію кодів статусу HTTP за групами (1xx, 2xx, 3xx, 4xx, 5xx).
- Зрозуміти семантику найпоширеніших кодів статусу та контекст їхнього використання.
- Навчитися правильно обирати код статусу для різних сценаріїв у REST API.
- Засвоїти різницю між схожими кодами (200 vs 201, 401 vs 403, 301 vs 302).
🔑 Ключові терміни
- Status Code — тризначне число у HTTP-відповіді, що вказує на результат обробки запиту.
- Informational (1xx) — інформаційні відповіді, обробка запиту продовжується.
- Successful (2xx) — успішна обробка запиту.
- Redirection (3xx) — клієнт повинен виконати додаткові дії для завершення запиту.
- Client Error (4xx) — помилка у запиті клієнта.
- Server Error (5xx) — помилка на сервері при обробці валідного запиту.
Класифікація кодів статусу
Коди статусу HTTP є тризначними числами, де перша цифра визначає категорію відповіді. Усього існує п'ять категорій, кожна з яких має чітко визначену семантику:
Загальна класифікація
| Діапазон | Категорія | Семантика | Дія клієнта |
|---|---|---|---|
| 1xx | Інформаційні (Informational) | Проміжна відповідь, запит отримано та обробляється | Очікувати фінальну відповідь |
| 2xx | Успішні (Successful) | Запит успішно оброблено | Використовувати отримані дані |
| 3xx | Перенаправлення (Redirection) | Потрібні додаткові дії для завершення запиту | Перейти за новою адресою |
| 4xx | Помилки клієнта (Client Error) | Запит містить помилку або не може бути оброблений | Виправити запит та повторити |
| 5xx | Помилки сервера (Server Error) | Сервер не зміг обробити валідний запит | Повторити пізніше або звернутися до адміністратора |
299 (нестандартний), він повинен інтерпретувати його як успішну відповідь (2xx), а не як помилку.Група 1xx: Інформаційні відповіді
Коди статусу діапазону 1xx є проміжними відповідями (interim responses), які інформують клієнта про те, що запит отримано та обробка продовжується. Ці коди не є фінальними — після них завжди слідує фінальна відповідь (2xx, 3xx, 4xx або 5xx).
100 Continue — Продовження надсилання тіла
Призначення: Клієнт надіслав частину запиту (стартовий рядок та заголовки) з заголовком Expect: 100-continue та очікує підтвердження від сервера перед надсиланням (потенційно великого) тіла запиту.
Використання:
Перед відправкою великого файлу (наприклад, 2 ГБ відео) клієнт може спочатку надіслати заголовки, щоб перевірити, чи сервер готовий прийняти такий запит (чи достатньо місця, чи коректний Content-Type, чи є права доступу). Якщо сервер відповідає 100 Continue, клієнт продовжує надсилати тіло. Якщо сервер повертає 417 Expectation Failed або іншу помилку, клієнт економить пропускну здатність, не відправляючи великий файл.
Приклад взаємодії:
Крок 1: Клієнт надсилає запит з Expect: 100-continue
POST /api/v1/videos/upload HTTP/1.1
Host: media.example.com
Content-Type: video/mp4
Content-Length: 2147483648
Expect: 100-continue
[Клієнт очікує відповідь перед надсиланням 2 ГБ тіла]
Крок 2: Сервер підтверджує готовність
HTTP/1.1 100 Continue
Крок 3: Клієнт надсилає тіло
[2 ГБ бінарних даних відео]
Крок 4: Фінальна відповідь
HTTP/1.1 201 Created
Location: https://media.example.com/api/v1/videos/xyz789
Content-Type: application/json
Content-Length: 123
{"id":"xyz789","status":"processing","uploadedAt":"2026-08-29T13:00:00Z"}
101 Switching Protocols — Перемикання протоколів
Призначення: Сервер погоджується змінити протокол на той, який запитав клієнт через заголовок Upgrade.
Використання:
Найчастіше використовується для апгрейду HTTP-з'єднання до WebSocket. Після відповіді 101 з'єднання більше не є HTTP — воно стає WebSocket, і обидві сторони обмінюються бінарними фреймами.
Приклад апгрейду до WebSocket:
Запит клієнта:
GET /chat HTTP/1.1
Host: realtime.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Відповідь сервера:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
[Після цього рядка з'єднання стає WebSocket]
102 Processing — Обробка (WebDAV)
Призначення: Сервер отримав запит та обробляє його, але фінальної відповіді ще немає. Використовується для запобігання таймауту клієнта при довготривалих операціях.
Контекст: Розширення WebDAV (RFC 2518) для роботи з файловими системами через HTTP.
Приклад:
HTTP/1.1 102 Processing
Сервер продовжує обробку, клієнт очікує фінальну відповідь.
103 Early Hints — Ранні підказки (експериментальний)
Призначення: Сервер надсилає клієнту підказки про ресурси, які будуть потрібні для рендерингу сторінки, перед формуванням фінальної відповіді. Це дозволяє браузеру почати завантаження CSS, JavaScript, шрифтів паралельно з обробкою запиту на сервері.
Приклад:
Крок 1: Ранні підказки
HTTP/1.1 103 Early Hints
Link: </styles/main.css>; rel=preload; as=style
Link: </scripts/app.js>; rel=preload; as=script
Link: </fonts/roboto.woff2>; rel=preload; as=font; crossorigin
Браузер починає завантажувати ці ресурси.
Крок 2: Фінальна відповідь (через 300 мс після обробки на сервері)
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 5678
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/styles/main.css">
<script src="/scripts/app.js"></script>
</head>
...
</html>
До моменту отримання HTML браузер вже завантажив частину ресурсів, що прискорює рендеринг.
Група 2xx: Успішні відповіді
Коди діапазону 2xx вказують, що запит клієнта був успішно отриманий, зрозумілий та оброблений сервером. Це єдина категорія кодів, яка свідчить про успішне завершення операції.
200 OK — Успішна обробка запиту
Призначення: Універсальний код успіху. Запит оброблено успішно, тіло відповіді містить запитувані дані або результат операції.
Використання: GET (отримання даних), POST (якщо не створюється новий ресурс), PUT/PATCH (оновлення з поверненням даних), DELETE (з підтвердженням).
Приклад 1: GET — отримання ресурсу
GET /api/v1/users/42 HTTP/1.1
Host: api.example.com
Відповідь:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 187
{"id":42,"email":"john@example.com","firstName":"John","lastName":"Doe","role":"user"}
Приклад 2: PATCH — оновлення з поверненням оновлених даних
PATCH /api/v1/users/42 HTTP/1.1
Content-Type: application/json
{"email":"john.new@example.com"}
Відповідь:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":42,"email":"john.new@example.com","firstName":"John","lastName":"Doe","updatedAt":"2026-08-29T13:10:00Z"}
201 Created — Ресурс успішно створено
Призначення: Запит успішно оброблено, і в результаті був створений новий ресурс. Відповідь повинна містити заголовок Location з URI новоствореного ресурсу.
Використання: POST (створення), PUT (створення ресурсу за вказаною адресою).
Приклад: POST — створення користувача
POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
{"email":"jane@example.com","firstName":"Jane","password":"SecurePass123!"}
Відповідь:
HTTP/1.1 201 Created
Location: https://api.example.com/api/v1/users/125
Content-Type: application/json; charset=utf-8
Content-Length: 156
{"id":125,"email":"jane@example.com","firstName":"Jane","createdAt":"2026-08-29T13:15:00Z","isActive":true}
Використовуйте
201 Created, коли операція створила новий ресурс, який має власний URI. Якщо POST виконує іншу операцію (пошук, обчислення, надсилання email) без створення ресурсу, використовуйте 200 OK.202 Accepted — Запит прийнято до обробки
Призначення: Запит прийнято для обробки, але обробка ще не завершена. Використовується для асинхронних операцій, які виконуються у фоновому режимі (черги, batch-обробка, довготривалі операції).
Використання: POST/PUT/DELETE для операцій, що виконуються асинхронно (генерація звіту, масове оновлення, обробка платежу).
Приклад: POST — генерація великого звіту
POST /api/v1/reports/generate HTTP/1.1
Content-Type: application/json
{"type":"annual","year":2026,"format":"pdf"}
Відповідь:
HTTP/1.1 202 Accepted
Location: https://api.example.com/api/v1/reports/tasks/abc-123
Content-Type: application/json; charset=utf-8
{"taskId":"abc-123","status":"processing","estimatedTime":300,"statusUrl":"/api/v1/reports/tasks/abc-123/status"}
Клієнт може періодично перевіряти статус через statusUrl:
GET /api/v1/reports/tasks/abc-123/status HTTP/1.1
Відповідь (обробка продовжується):
HTTP/1.1 200 OK
Content-Type: application/json
{"taskId":"abc-123","status":"processing","progress":45}
Відповідь (обробка завершена):
HTTP/1.1 200 OK
Content-Type: application/json
{"taskId":"abc-123","status":"completed","downloadUrl":"/api/v1/reports/abc-123/download"}
203 Non-Authoritative Information — Неавторитетна інформація
Призначення: Успішна відповідь, але дані були модифіковані проміжним проксі (наприклад, додано або видалено заголовки, трансформовано контент).
Використання: Рідко використовується, в основному проксі-серверами або CDN.
204 No Content — Успіх без тіла відповіді
Призначення: Запит успішно оброблено, але тіло відповіді порожнє. Клієнт не повинен оновлювати поточне представлення документа.
Використання: DELETE (видалення без підтвердження), PUT/PATCH (оновлення без повернення даних).
Приклад 1: DELETE — видалення користувача
DELETE /api/v1/users/42 HTTP/1.1
Authorization: Bearer eyJhbGc...admin-token...
Відповідь:
HTTP/1.1 204 No Content
Date: Sat, 29 Aug 2026 13:20:00 GMT
Тіло порожнє, клієнт знає, що операція успішна.
Приклад 2: PUT — оновлення налаштувань
PUT /api/v1/users/42/settings HTTP/1.1
Content-Type: application/json
{"notifications":true,"theme":"dark"}
Відповідь:
HTTP/1.1 204 No Content
205 Reset Content — Скинути вміст
Призначення: Запит успішно оброблено, клієнт повинен скинути поточне представлення документа (очистити форму, оновити інтерфейс).
Використання: Рідко використовується, зазвичай після відправки форми для очищення полів.
206 Partial Content — Часткове вміст
Призначення: Сервер повертає частину ресурсу, запитану клієнтом через заголовок Range. Використовується для часткового завантаження великих файлів (відео, аудіо, великі документи) або відновлення перерваного завантаження.
Приклад: Часткове завантаження відео
Запит (перші 1 МБ файлу):
GET /videos/movie.mp4 HTTP/1.1
Host: cdn.example.com
Range: bytes=0-1048575
Відповідь:
HTTP/1.1 206 Partial Content
Content-Type: video/mp4
Content-Length: 1048576
Content-Range: bytes 0-1048575/524288000
Accept-Ranges: bytes
[1 МБ бінарних даних відео]
Клієнт може запитувати наступні частини:
Range: bytes=1048576-2097151
Сервер сигналізує про підтримку часткових запитів через заголовок
Accept-Ranges: bytes у відповіді на звичайний GET або HEAD запит. Якщо сервер не підтримує діапазони, він повертає Accept-Ranges: none та завжди віддає файл цілком.Група 3xx: Перенаправлення
Коди діапазону 3xx інформують клієнта, що для завершення запиту потрібні додаткові дії — зазвичай перехід за іншою адресою. Браузери автоматично виконують перенаправлення, але програмні HTTP-клієнти повинні явно обробляти ці коди.
300 Multiple Choices — Множинний вибір
Призначення: Запитуваний ресурс має кілька можливих представлень, і клієнт повинен обрати одне з них (наприклад, різні мови, формати файлів).
Використання: Рідко застосовується на практиці.
301 Moved Permanently — Назавжди переміщено
Призначення: Ресурс назавжди переміщено на нову адресу, вказану у заголовку Location. Клієнт (і пошукові системи) повинні оновити збережені посилання та використовувати нову адресу у майбутньому.
Використання: Зміна структури URL, перейменування домену, об'єднання сторінок.
Приклад:
Запит (стара адреса):
GET /old-products HTTP/1.1
Host: www.example.com
Відповідь:
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/products
Content-Length: 0
Браузер автоматично переходить на https://www.example.com/products та зберігає нову адресу — наступні запити йдуть одразу на нову URL без перенаправлення.
Пошукові системи (Google, Bing) інтерпретують
301 як постійне перенаправлення та передають рейтинг старої сторінки на нову. Використовуйте 301 обережно — повернення назад вимагає часу для переіндексації.302 Found — Тимчасово знайдено (тимчасове перенаправлення)
Призначення: Ресурс тимчасово доступний за іншою адресою. Клієнт повинен використовувати нову адресу лише для цього запиту, але продовжувати використовувати оригінальну URL у майбутньому.
Використання: Тимчасова недоступність, A/B тестування, перенаправлення після логіну.
Приклад: Перенаправлення після логіну
Запит (POST логін):
POST /auth/login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
email=user@example.com&password=pass123
Відповідь:
HTTP/1.1 302 Found
Location: https://www.example.com/dashboard
Set-Cookie: sessionId=xyz789; HttpOnly; Secure
Content-Length: 0
Браузер переходить на /dashboard, але при наступному логіні знову відправляє POST на /auth/login.
303 See Other — Дивіться інше
Призначення: Відповідь на запит знаходиться за іншою адресою і повинна бути отримана через GET-запит (навіть якщо оригінальний запит був POST/PUT/DELETE).
Використання: Перенаправлення після POST для уникнення повторного відправлення форми при оновленні сторінки (Pattern: POST-Redirect-GET).
Приклад: POST-Redirect-GET pattern
Крок 1: Клієнт створює ресурс
POST /api/v1/articles HTTP/1.1
Content-Type: application/json
{"title":"My Article","content":"..."}
Крок 2: Сервер створює ресурс та перенаправляє на його GET
HTTP/1.1 303 See Other
Location: https://blog.example.com/api/v1/articles/new-article-123
Content-Length: 0
Крок 3: Браузер автоматично відправляє GET
GET /api/v1/articles/new-article-123 HTTP/1.1
Крок 4: Відповідь з даними статті
HTTP/1.1 200 OK
Content-Type: application/json
{"id":"new-article-123","title":"My Article","createdAt":"..."}
Якщо користувач оновить сторінку (F5), повторно виконається лише безпечний GET, а не POST.
304 Not Modified — Не змінювався
Призначення: Ресурс не змінювався з моменту, вказаного у заголовках умовного запиту (If-None-Match, If-Modified-Since). Клієнт може використовувати закешовану версію.
Використання: Економія пропускної здатності через умовні запити.
Приклад: Умовний GET з ETag
Запит (клієнт має закешовану версію):
GET /api/v1/products/42 HTTP/1.1
Host: api.example.com
If-None-Match: "product-v3-hash789"
Відповідь (ресурс не змінився):
HTTP/1.1 304 Not Modified
ETag: "product-v3-hash789"
Cache-Control: public, max-age=3600
Content-Length: 0
Тіло порожнє — клієнт використовує закешовані дані.
Відповідь (ресурс оновився):
HTTP/1.1 200 OK
ETag: "product-v4-hash012"
Content-Type: application/json
Content-Length: 245
{"id":42,"name":"Updated Product","price":29999,...}
307 Temporary Redirect — Тимчасове перенаправлення (зберігає метод)
Призначення: Аналогічно до 302, але гарантує збереження методу запиту. Якщо оригінальний запит був POST, перенаправлений запит також буде POST.
Відмінність від 302:
Історично деякі браузери змінювали POST на GET при перенаправленні 302. Код 307 забороняє таку поведінку.
Приклад:
Запит:
POST /api/v1/orders HTTP/1.1
Content-Type: application/json
{"productId":123,"quantity":2}
Відповідь:
HTTP/1.1 307 Temporary Redirect
Location: https://api-new.example.com/api/v1/orders
Content-Length: 0
Браузер повторює POST (не GET) на нову адресу з тим самим тілом.
308 Permanent Redirect — Постійне перенаправлення (зберігає метод)
Призначення: Аналогічно до 301, але гарантує збереження методу запиту. Ресурс назавжди переміщено, і метод запиту не повинен змінюватися.
Приклад:
HTTP/1.1 308 Permanent Redirect
Location: https://new-domain.example.com/api/v1/users
POST залишається POST при перенаправленні.
Група 4xx: Помилки клієнта
Коди діапазону 4xx вказують, що запит містить помилку з боку клієнта — неправильний синтаксис, невалідні дані, відсутність автентифікації або прав доступу. Сервер не повинен повторювати обробку такого запиту без виправлень з боку клієнта.
400 Bad Request — Неправильний запит
Призначення: Сервер не може або не хоче обробляти запит через помилку синтаксису або невалідні дані.
Використання: Некоректний JSON, відсутні обов'язкові поля, невалідний формат даних, порушення бізнес-правил.
Приклад 1: Некоректний JSON
Запит:
POST /api/v1/users HTTP/1.1
Content-Type: application/json
{"email":"john@example.com","name":John}
(відсутні лапки навколо John)
Відповідь:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{"error":"Bad Request","message":"Invalid JSON syntax: expected string at line 1, column 37"}
Приклад 2: Валідація даних
Запит:
POST /api/v1/users HTTP/1.1
Content-Type: application/json
{"email":"invalid-email","password":"123"}
Відповідь:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{"error":"Validation Failed","details":[{"field":"email","message":"Must be a valid email address"},{"field":"password","message":"Must be at least 8 characters"}]}
401 Unauthorized — Необхідна автентифікація
Призначення: Запит вимагає автентифікації користувача. Клієнт або не надав облікові дані, або надав невалідні/прострочені.
Назва заплутана: Насправді означає Unauthenticated (не автентифікований), а не Unauthorized (не авторизований).
Використання: Відсутній токен, невалідний JWT, прострочена сесія.
Приклад 1: Відсутній токен
Запит:
GET /api/v1/users/me HTTP/1.1
Host: api.example.com
Відповідь:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="API"
Content-Type: application/json; charset=utf-8
{"error":"Unauthorized","message":"Authentication required. Please provide a valid access token."}
Заголовок WWW-Authenticate вказує схему автентифікації (Bearer).
Приклад 2: Невалідний токен
Запит:
GET /api/v1/users/me HTTP/1.1
Authorization: Bearer invalid-or-expired-token-xyz
Відповідь:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="Token has expired"
Content-Type: application/json
{"error":"Unauthorized","message":"Access token has expired. Please refresh your token."}
402 Payment Required — Необхідна оплата
Призначення: Зарезервовано для майбутнього використання. Передбачалося для систем цифрових платежів, але так і не було стандартизовано.
Використання: Деякі API використовують 402 для позначення вичерпаного ліміту (rate limit) або необхідності оплати підписки.
403 Forbidden — Доступ заборонено
Призначення: Сервер зрозумів запит, але відмовляє у доступі. Автентифікація не допоможе — у користувача немає прав на цю операцію.
Відмінність від 401:
- 401: Немає або невалідна автентифікація → надайте облікові дані.
- 403: Автентифікація є, але недостатньо прав → запитайте доступ у адміністратора.
Приклад: Недостатньо прав для видалення
Запит (від звичайного користувача):
DELETE /api/v1/users/10 HTTP/1.1
Authorization: Bearer user-token-xyz
Відповідь:
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
{"error":"Forbidden","message":"You do not have permission to delete users. Required role: admin"}
404 Not Found — Ресурс не знайдено
Призначення: Сервер не знайшов запитуваний ресурс. URL може бути неправильним, або ресурс було видалено.
Використання: Невірний URI, видалений ресурс, несніснуючий ID.
Приклад:
Запит:
GET /api/v1/users/99999 HTTP/1.1
Host: api.example.com
Відповідь:
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{"error":"Not Found","message":"User with ID 99999 does not exist"}
Якщо ресурс було тимчасово видалено і може з'явитися знову, використовуйте
404. Якщо ресурс назавжди видалено, використовуйте 410 Gone.405 Method Not Allowed — Метод не дозволено
Призначення: Метод запиту не підтримується для даного ресурсу. Відповідь повинна містити заголовок Allow зі списком дозволених методів.
Використання: Спроба DELETE на read-only ресурс, POST на endpoint, що підтримує лише GET.
Приклад:
Запит (спроба видалити системний ресурс):
DELETE /api/v1/system/config HTTP/1.1
Відповідь:
HTTP/1.1 405 Method Not Allowed
Allow: GET, PUT
Content-Type: application/json
{"error":"Method Not Allowed","message":"DELETE is not supported for this resource. Allowed methods: GET, PUT"}
406 Not Acceptable — Неприйнятний формат
Призначення: Сервер не може згенерувати відповідь у форматі, запитаному клієнтом через заголовок Accept.
Приклад:
Запит (клієнт хоче XML):
GET /api/v1/users/42 HTTP/1.1
Accept: application/xml
Відповідь (сервер підтримує лише JSON):
HTTP/1.1 406 Not Acceptable
Content-Type: application/json
{"error":"Not Acceptable","message":"Server only supports application/json. Requested format application/xml is not available."}
408 Request Timeout — Таймаут запиту
Призначення: Клієнт не надіслав повний запит у відведений час. Сервер закриває з'єднання.
Використання: Повільне з'єднання, клієнт завис при надсиланні великого тіла.
409 Conflict — Конфлікт
Призначення: Запит конфліктує з поточним станом ресурсу на сервері. Зазвичай при спробі створити дублікат або порушенні бізнес-правил.
Приклад 1: Дублікат email
Запит:
POST /api/v1/users HTTP/1.1
Content-Type: application/json
{"email":"existing@example.com","password":"pass123"}
Відповідь:
HTTP/1.1 409 Conflict
Content-Type: application/json
{"error":"Conflict","message":"User with email 'existing@example.com' already exists","field":"email"}
Приклад 2: Конфлікт версій (optimistic locking)
Запит:
PUT /api/v1/documents/42 HTTP/1.1
If-Match: "version-5"
Content-Type: application/json
{"title":"Updated Title"}
Відповідь (документ вже оновлено іншим користувачем):
HTTP/1.1 409 Conflict
ETag: "version-7"
Content-Type: application/json
{"error":"Conflict","message":"Document was modified by another user. Current version: 7, your version: 5"}
410 Gone — Назавжди видалено
Призначення: Ресурс раніше існував, але був назавжди видалений і більше не буде доступним.
Відмінність від 404:
- 404: Ресурс не знайдено (можливо, ніколи не існував або тимчасово недоступний).
- 410: Ресурс точно існував, але навмисно видалений назавжди.
Приклад:
Запит:
GET /api/v1/articles/old-article-2020 HTTP/1.1
Відповідь:
HTTP/1.1 410 Gone
Content-Type: application/json
{"error":"Gone","message":"This article was permanently removed on 2023-01-15 due to outdated information."}
411 Length Required — Необхідна довжина
Призначення: Сервер відмовляється приймати запит без заголовка Content-Length.
Приклад:
Запит (без Content-Length):
POST /api/v1/upload HTTP/1.1
Content-Type: application/octet-stream
[дані без вказаної довжини]
Відповідь:
HTTP/1.1 411 Length Required
Content-Type: application/json
{"error":"Length Required","message":"Request must include Content-Length header"}
413 Payload Too Large — Тіло запиту занадто велике
Призначення: Тіло запиту перевищує ліміт, встановлений сервером (розмір файлу, розмір JSON, тощо).
Приклад:
Запит (файл 15 МБ):
POST /api/v1/avatars HTTP/1.1
Content-Type: image/jpeg
Content-Length: 15728640
[15 МБ зображення]
Відповідь (ліміт 5 МБ):
HTTP/1.1 413 Payload Too Large
Content-Type: application/json
Retry-After: 3600
{"error":"Payload Too Large","message":"Maximum file size is 5 MB. Your file: 15 MB","maxSize":5242880}
Заголовок Retry-After може вказувати, коли спробувати знову (якщо ліміт тимчасовий).
415 Unsupported Media Type — Непідтримуваний тип медіа
Призначення: Сервер відмовляється обробити запит, тому що формат даних (Content-Type) не підтримується.
Приклад:
Запит (XML замість JSON):
POST /api/v1/users HTTP/1.1
Content-Type: application/xml
<user><email>john@example.com</email></user>
Відповідь (сервер приймає лише JSON):
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/json
Accept: application/json
{"error":"Unsupported Media Type","message":"Server only accepts application/json. Received: application/xml"}
422 Unprocessable Entity — Необроблювана сутність
Призначення: Запит синтаксично коректний, але сервер не може обробити його через семантичні помилки (невалідні дані згідно бізнес-логіки).
Відмінність від 400:
- 400: Синтаксична помилка (некоректний JSON, невалідний формат).
- 422: Синтаксис правильний, але дані невалідні згідно правил (наприклад, дата народження у майбутньому).
Приклад:
Запит:
POST /api/v1/bookings HTTP/1.1
Content-Type: application/json
{"roomId":42,"checkIn":"2026-08-30","checkOut":"2026-08-25"}
Відповідь (checkOut раніше checkIn):
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{"error":"Unprocessable Entity","message":"Check-out date cannot be before check-in date","details":[{"field":"checkOut","message":"Must be after checkIn (2026-08-30)"}]}
429 Too Many Requests — Забагато запитів
Призначення: Клієнт надіслав занадто багато запитів за короткий період часу (rate limiting).
Використання: Захист API від зловживань, DoS-атак, надмірного навантаження.
Приклад:
Запит (51-й запит за хвилину):
GET /api/v1/search?q=laptop HTTP/1.1
Відповідь (ліміт 50 запитів/хвилину):
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 42
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1693315200
{"error":"Too Many Requests","message":"Rate limit exceeded. Maximum 50 requests per minute. Try again in 42 seconds."}
Заголовки rate limiting:
X-RateLimit-Limit: 50— максимальна кількість запитів у вікні.X-RateLimit-Remaining: 0— скільки запитів залишилося.X-RateLimit-Reset: 1693315200— Unix timestamp скидання ліміту.Retry-After: 42— через скільки секунд можна повторити.
451 Unavailable For Legal Reasons — Недоступно з юридичних причин
Призначення: Доступ до ресурсу заблоковано через юридичні вимоги (цензура, авторське право, судовий припис).
Приклад:
Запит:
GET /news/article/censored-content HTTP/1.1
Host: news.example.com
Відповідь:
HTTP/1.1 451 Unavailable For Legal Reasons
Content-Type: text/html; charset=utf-8
Link: <https://example.com/legal-block-notice>; rel="blocked-by"
<!DOCTYPE html>
<html>
<head><title>Content Blocked</title></head>
<body>
<h1>451 Unavailable For Legal Reasons</h1>
<p>This content is blocked in your region due to court order #2026-XYZ.</p>
<p><a href="https://example.com/legal-block-notice">More information</a></p>
</body>
</html>
Код 451 — це відсилка до роману "Fahrenheit 451" Рея Бредбері, де книги спалюються режимом. Температура 451°F (233°C) — це температура займання паперу.
Група 5xx: Помилки сервера
Коди діапазону 5xx вказують, що сервер не зміг виконати валідний запит через внутрішню помилку або тимчасову недоступність. Клієнт може повторити запит пізніше, оскільки помилка на стороні сервера, а не клієнта.
500 Internal Server Error — Внутрішня помилка сервера
Призначення: Універсальна помилка сервера. Сервер зіткнувся з несподіваною умовою, яка перешкодила обробці запиту.
Використання: Необроблений виняток, помилка у коді, збій бази даних, відсутнє з'єднання.
Приклад:
Запит:
GET /api/v1/products HTTP/1.1
Відповідь (помилка у базі даних):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{"error":"Internal Server Error","message":"An unexpected error occurred. Please try again later.","requestId":"req-abc-123"}
У продакшн-середовищі НЕ розкривайте деталі помилки (стектрейс, SQL-запити, шляхи до файлів) у відповіді 500. Це може надати зловмисникам інформацію про архітектуру системи. Логуйте деталі на сервері, а клієнту повертайте загальне повідомлення з
requestId для відстеження.501 Not Implemented — Не реалізовано
Призначення: Сервер не підтримує функціональність, необхідну для обробки запиту. Зазвичай означає, що сервер не розпізнає метод запиту.
Приклад:
Запит (QUERY — новий метод):
QUERY /api/v1/search HTTP/1.1
Content-Type: application/query+json
{"query":"SELECT * FROM products WHERE price < 1000"}
Відповідь (сервер не підтримує QUERY):
HTTP/1.1 501 Not Implemented
Content-Type: application/json
{"error":"Not Implemented","message":"HTTP method QUERY is not supported by this server"}
502 Bad Gateway — Помилка шлюзу
Призначення: Сервер, діючи як шлюз або проксі, отримав невалідну відповідь від upstream-сервера.
Використання: Проксі не може з'єднатися з backend, backend повернув некоректну відповідь, помилка у reverse proxy (nginx, HAProxy).
Приклад (nginx як reverse proxy):
Запит:
GET /api/v1/users HTTP/1.1
Host: api.example.com
Відповідь (backend-сервер недоступний):
HTTP/1.1 502 Bad Gateway
Content-Type: text/html
Server: nginx/1.25.0
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<h1>502 Bad Gateway</h1>
<p>nginx could not connect to upstream server</p>
</body>
</html>
503 Service Unavailable — Сервіс недоступний
Призначення: Сервер тимчасово не може обробляти запити через перевантаження або технічне обслуговування. Це тимчасовий стан.
Використання: Технічне обслуговування, перевантаження, deployment, перезапуск сервісу.
Приклад:
Запит:
GET /api/v1/orders HTTP/1.1
Відповідь:
HTTP/1.1 503 Service Unavailable
Content-Type: application/json
Retry-After: 1800
{"error":"Service Unavailable","message":"System is undergoing scheduled maintenance. Service will be available in 30 minutes.","estimatedResume":"2026-08-29T15:00:00Z"}
Заголовок Retry-After: 1800 вказує клієнту повторити запит через 1800 секунд (30 хвилин).
504 Gateway Timeout — Таймаут шлюзу
Призначення: Сервер, діючи як шлюз або проксі, не отримав своєчасну відповідь від upstream-сервера.
Відмінність від 502:
- 502: Отримано невалідну відповідь від upstream.
- 504: Взагалі не отримано відповіді у відведений час.
Приклад:
Запит (довга операція):
POST /api/v1/reports/heavy-calculation HTTP/1.1
Відповідь (backend не відповів за 60 секунд):
HTTP/1.1 504 Gateway Timeout
Content-Type: application/json
Server: nginx/1.25.0
{"error":"Gateway Timeout","message":"Upstream server did not respond within 60 seconds. Please try again or use asynchronous processing."}
511 Network Authentication Required — Необхідна автентифікація мережі
Призначення: Клієнт повинен автентифікуватися у мережі перед доступом до ресурсу. Використовується captive portal (публічний Wi-Fi у кафе, готелі, аеропорту).
Приклад (Wi-Fi у готелі):
Запит:
GET /api/v1/news HTTP/1.1
Host: example.com
Відповідь (перехоплено captive portal):
HTTP/1.1 511 Network Authentication Required
Content-Type: text/html
<html>
<head><title>Hotel Wi-Fi Login</title></head>
<body>
<h1>Welcome to Hotel Wi-Fi</h1>
<p>Please log in to access the internet</p>
<form action="/wifi-login" method="POST">
<input name="room" placeholder="Room number">
<input name="surname" placeholder="Surname">
<button type="submit">Connect</button>
</form>
</body>
</html>
Візуалізація потоків обробки кодів статусу
@startuml HTTP Status Code Decision Flow
skinparam backgroundColor #FEFEFE
skinparam handwritten false
skinparam defaultFontName Arial
skinparam shadowing false
start
:Клієнт надсилає HTTP-запит;
if (Сервер отримав запит?) then (так)
if (Запит потребує проміжної відповіді?) then (так)
:Відправити **1xx Informational**;
note right
100 Continue
101 Switching Protocols
103 Early Hints
end note
endif
if (Запит валідний?) then (так)
if (Автентифікація потрібна?) then (так)
if (Облікові дані надано?) then (так)
if (Облікові дані валідні?) then (так)
:Перевірка авторизації;
else (ні)
:Відправити **401 Unauthorized**;
stop
endif
else (ні)
:Відправити **401 Unauthorized**;
stop
endif
endif
if (Є права доступу?) then (так)
if (Ресурс існує?) then (так)
if (Метод дозволений?) then (так)
if (Ліміт запитів не вичерпано?) then (так)
:Обробка запиту на сервері;
if (Обробка успішна?) then (так)
if (Створено новий ресурс?) then (так)
:Відправити **201 Created**;
stop
else (ні)
if (Є дані для повернення?) then (так)
:Відправити **200 OK**;
stop
else (ні)
:Відправити **204 No Content**;
stop
endif
endif
else (помилка сервера)
:Відправити **500 Internal Server Error**;
stop
endif
else (ні)
:Відправити **429 Too Many Requests**;
stop
endif
else (ні)
:Відправити **405 Method Not Allowed**;
stop
endif
else (ні, але була перенаправлення)
if (Перенаправлення постійне?) then (так)
:Відправити **301 Moved Permanently**;
stop
else (тимчасове)
:Відправити **302 Found / 307 Temporary Redirect**;
stop
endif
endif
:Відправити **404 Not Found**;
stop
else (ні)
:Відправити **403 Forbidden**;
stop
endif
else (невалідний)
if (Синтаксична помилка?) then (так)
:Відправити **400 Bad Request**;
stop
else (семантична помилка)
:Відправити **422 Unprocessable Entity**;
stop
endif
endif
else (помилка мережі)
:Відправити **502 Bad Gateway / 504 Gateway Timeout**;
stop
endif
@enduml
Порівняльна таблиця схожих кодів статусу
Багато кодів статусу мають схожу семантику, що може викликати плутанину. Нижче наведено порівняльну таблицю для роз'яснення відмінностей:
200 OK vs 201 Created vs 204 No Content
| Код | Коли використовувати | Тіло відповіді | Приклад |
|---|---|---|---|
| 200 OK | Успішна обробка, дані повертаються | Так | GET /users/42 → повертає дані користувача |
| 201 Created | Створено новий ресурс | Так (дані нового ресурсу) + Location | POST /users → створено користувача |
| 204 No Content | Успішна обробка, дані НЕ повертаються | Ні | DELETE /users/42 → користувача видалено |
301 Moved Permanently vs 302 Found vs 307 Temporary Redirect vs 308 Permanent Redirect
| Код | Тривалість | Зберігає метод? | Використання |
|---|---|---|---|
| 301 Moved Permanently | Постійне | Ні (може змінити POST→GET) | Зміна домену, SEO |
| 302 Found | Тимчасове | Ні (може змінити POST→GET) | Тимчасове перенаправлення, A/B тести |
| 307 Temporary Redirect | Тимчасове | Так (POST залишається POST) | Тимчасове перенаправлення з POST |
| 308 Permanent Redirect | Постійне | Так (POST залишається POST) | Постійне перенаправлення з POST |
400 Bad Request vs 422 Unprocessable Entity
| Код | Тип помилки | Коли використовувати | Приклад |
|---|---|---|---|
| 400 Bad Request | Синтаксична | Некоректний JSON, невалідний формат, порушення HTTP-протоколу | {"email": invalid} (некоректний JSON) |
| 422 Unprocessable Entity | Семантична | Синтаксис правильний, але дані невалідні згідно бізнес-логіки | {"age": -5} (вік не може бути від'ємним) |
401 Unauthorized vs 403 Forbidden
| Код | Проблема | Рішення | Приклад |
|---|---|---|---|
| 401 Unauthorized | Відсутня або невалідна автентифікація | Надати валідні облікові дані (логін, токен) | Токен прострочений → увійдіть знову |
| 403 Forbidden | Недостатньо прав (автентифікація є) | Запитати доступ у адміністратора, змінити роль | Звичайний користувач намагається видалити інших |
404 Not Found vs 410 Gone
| Код | Семантика | Чи існував ресурс? | SEO наслідки |
|---|---|---|---|
| 404 Not Found | Ресурс не знайдено | Невідомо (можливо, ніколи не існував) | Пошукові системи повторюють індексацію |
| 410 Gone | Ресурс назавжди видалено | Так, існував раніше | Пошукові системи видаляють з індексу |
502 Bad Gateway vs 503 Service Unavailable vs 504 Gateway Timeout
| Код | Причина | Хто відповідає | Дія клієнта |
|---|---|---|---|
| 502 Bad Gateway | Невалідна відповідь від upstream | Проксі/шлюз | Повторити (можливо, backend перезапускається) |
| 503 Service Unavailable | Сервер перевантажений або на обслуговуванні | Сам сервер | Повторити через час, вказаний у Retry-After |
| 504 Gateway Timeout | Upstream не відповів вчасно | Проксі/шлюз | Повторити або перейти на асинхронну обробку |
Узагальнення: Вибір правильного коду статусу
✅ Успішні операції (2xx)
- 200 OK: Універсальний успіх, дані повертаються
- 201 Created: Створено новий ресурс +
Location - 202 Accepted: Запит прийнято, обробка асинхронна
- 204 No Content: Успіх без тіла відповіді (DELETE, PUT)
- 206 Partial Content: Часткове завантаження (Range)
➡️ Перенаправлення (3xx)
- 301 Moved Permanently: Ресурс назавжди переміщено (SEO)
- 302 Found / 307: Тимчасове перенаправлення
- 303 See Other: POST → GET редірект
- 304 Not Modified: Використовувати кеш (умовний GET)
❌ Помилки клієнта (4xx)
- 400 Bad Request: Синтаксична помилка
- 401 Unauthorized: Немає автентифікації
- 403 Forbidden: Немає прав доступу
- 404 Not Found: Ресурс не знайдено
- 422 Unprocessable Entity: Семантична помилка
- 429 Too Many Requests: Перевищено rate limit
⚠️ Помилки сервера (5xx)
- 500 Internal Server Error: Загальна помилка сервера
- 502 Bad Gateway: Помилка upstream-сервера
- 503 Service Unavailable: Тимчасово недоступний
- 504 Gateway Timeout: Upstream не відповів вчасно
Контрольні питання та завдання
Завдання: Класифікуйте наступні коди статусу за категоріями (1xx, 2xx, 3xx, 4xx, 5xx) та поясніть їхнє призначення:
a) 201
b) 404
c) 503
d) 301
e) 422
Відповіді:
a) 201 Created — категорія 2xx (Успішні). Ресурс успішно створено, відповідь містить Location з URI нового ресурсу.
b) 404 Not Found — категорія 4xx (Помилки клієнта). Запитуваний ресурс не знайдено на сервері.
c) 503 Service Unavailable — категорія 5xx (Помилки сервера). Сервер тимчасово не може обробляти запити (обслуговування, перевантаження).
d) 301 Moved Permanently — категорія 3xx (Перенаправлення). Ресурс назавжди переміщено на нову адресу, клієнт повинен оновити збережені посилання.
e) 422 Unprocessable Entity — категорія 4xx (Помилки клієнта). Запит синтаксично коректний, але містить семантичні помилки (невалідні дані згідно бізнес-правил).
::
Завдання: Поясніть різницю між кодами 401 Unauthorized та 403 Forbidden. Наведіть приклади ситуацій, коли слід використовувати кожен з них.
Відповідь:
401 Unauthorized (насправді означає "Unauthenticated"):
- Проблема: Відсутня або невалідна автентифікація.
- Рішення: Клієнт повинен надати валідні облікові дані (токен, логін/пароль).
- Приклад: Користувач не увійшов у систему або токен прострочений.
403 Forbidden:
- Проблема: Автентифікація є валідною, але недостатньо прав для виконання операції.
- Рішення: Запитати доступ у адміністратора або змінити роль користувача.
- Приклад: Звичайний користувач (role: user) намагається видалити інших користувачів (потрібна роль admin).
Ключова відмінність:
401 → "Хто ти?" (потрібна автентифікація)
403 → "Я знаю, хто ти, але тобі не дозволено" (недостатньо прав)
Завдання: Виберіть найбільш підхожий код статусу для наступних сценаріїв REST API:
a) Клієнт створює нового користувача через POST /api/users, операція успішна.
b) Клієнт надсилає DELETE /api/products/123, продукт видалено, підтвердження не потрібне.
c) Клієнт надсилає POST /api/users з email, що вже існує в базі.
d) Клієнт надсилає GET /api/orders без токена автентифікації.
e) Клієнт надсилає 55-й запит за хвилину при ліміті 50 запитів/хвилину.
Відповіді:
a) 201 Created — створено новий ресурс. Відповідь повинна містити заголовок Location: /api/users/456 з URI новоствореного користувача та тіло з даними користувача.
b) 204 No Content — операція успішна, дані не повертаються. Тіло відповіді порожнє.
c) 409 Conflict — запит конфліктує з поточним станом (дублікат email). Альтернативно можна використати 422 Unprocessable Entity, якщо це розглядається як порушення бізнес-правил.
d) 401 Unauthorized — відсутня автентифікація. Відповідь повинна містити заголовок WWW-Authenticate: Bearer realm="API".
e) 429 Too Many Requests — перевищено ліміт запитів. Відповідь повинна містити заголовки Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
Завдання: Проаналізуйте наступну HTTP-взаємодію та відповідь на питання:
POST /api/v1/articles HTTP/1.1
Host: blog.example.com
Content-Type: application/json
Authorization: Bearer user-token-abc
{"title":"My Article"}
Відповідь:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{"error":"Validation Failed","details":[{"field":"content","message":"Content is required"}]}
Питання:
- Чому сервер повернув 422, а не 400?
- Чи була автентифікація успішною?
- Що повинен зробити клієнт для виправлення помилки?
- Чи правильно обрано код статусу? Обгрунтуйте.
Відповіді:
- Чому 422, а не 400?
Запит є синтаксично коректним (валідний JSON, правильна структура), тому 400 не підходить. Помилка є семантичною — відсутнє обов'язкове полеcontentзгідно бізнес-правил валідації. 422 Unprocessable Entity саме для таких випадків. - Чи була автентифікація успішною?
Так, автентифікація успішна. Якби токен був невалідним або відсутнім, сервер повернув би 401 Unauthorized. Сервер дійшов до етапу валідації даних, що означає успішну автентифікацію. - Що повинен зробити клієнт?
Клієнт повинен додати полеcontentдо тіла запиту та повторити POST:{"title":"My Article","content":"Article text here..."} - Чи правильно обрано код статусу?
Так, 422 є правильним вибором. Альтернативно можна було використати 400, але 422 більш точно описує семантичну природу помилки та дозволяє клієнту зрозуміти, що синтаксис коректний, але дані невалідні.
Завдання: Розробіть структуру відповіді для endpoint /api/v1/search, який має ліміт 100 запитів на годину. Клієнт надіслав 101-й запит. Яку відповідь повинен повернути сервер? Включіть усі необхідні заголовки та тіло.
Відповідь:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json; charset=utf-8
Retry-After: 2847
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1693318047
X-RateLimit-Window: 3600
Date: Sat, 29 Aug 2026 14:00:00 GMT
Content-Length: 189
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 100 requests per hour.",
"limit": 100,
"remaining": 0,
"resetAt": "2026-08-29T14:47:27Z",
"retryAfterSeconds": 2847
}
Пояснення заголовків:
Retry-After: 2847— через скільки секунд можна повторити запит (2847 сек = ~47 хвилин).X-RateLimit-Limit: 100— максимальна кількість запитів у вікні (годині).X-RateLimit-Remaining: 0— скільки запитів залишилося (вичерпано).X-RateLimit-Reset: 1693318047— Unix timestamp (секунди з 1970-01-01) моменту скидання ліміту.X-RateLimit-Window: 3600— розмір вікна у секундах (3600 = 1 година).
Примітка: Стандарту для заголовків rate limiting не існує, але ці назви є найпоширенішими (використовуються GitHub, Twitter, Stripe).
Завдання: Клієнт завантажує відео файл розміром 500 МБ через POST /api/v1/videos/upload. Сервер підтримує ліміт 100 МБ. Який код статусу повинен повернути сервер? Напишіть RAW HTTP-відповідь з усіма необхідними заголовками.
Відповідь:
HTTP/1.1 413 Payload Too Large
Content-Type: application/json; charset=utf-8
Retry-After: 3600
Content-Length: 203
Date: Sat, 29 Aug 2026 14:15:00 GMT
{
"error": "Payload Too Large",
"message": "File size exceeds maximum allowed size",
"maxSizeBytes": 104857600,
"maxSizeMB": 100,
"receivedSizeBytes": 524288000,
"receivedSizeMB": 500,
"suggestion": "Split video into chunks or compress before uploading"
}
Пояснення:
- 413 Payload Too Large — правильний код для ситуації, коли розмір тіла запиту перевищує ліміт сервера.
- Retry-After: 3600 — можна спробувати знову через годину (якщо ліміт тимчасовий, наприклад, щоденна квота). Якщо ліміт постійний, заголовок не обов'язковий.
- Тіло містить детальну інформацію про ліміти та рекомендацію щодо виправлення (chunked upload, компресія).
Альтернативний підхід:
Використання заголовка Expect: 100-continue дозволяє клієнту перевірити можливість завантаження перед відправкою великого файлу, економлячи пропускну здатність.
::
Додаткові ресурси
- RFC 9110: HTTP Semantics — офіційна специфікація кодів статусу HTTP.
- MDN Web Docs: HTTP Status Codes — детальна документація з прикладами.
- httpstatuses.com — швидкий довідник кодів статусу з поясненнями.
- REST API Design Best Practices — рекомендації щодо вибору кодів статусу у REST API.