Статус коды: успешные запросы (2xx)
Введение: билет на поезд 🚆
Когда вы покупаете билет, вы получаете подтверждение: поезд принят, место закреплено, правила известны.
2xx‑коды — это такие же подтверждения от сервера: действие успешно, но какой именно успех — важно уточнить.
2xx‑коды — это такие же подтверждения от сервера: действие успешно, но какой именно успех — важно уточнить.
💡 Совет: успех — это не всегда «просто ок». Выбирайте код, который объясняет результат.
✅ Вывод: 2xx = «успешно», но с чёткой детализацией.
✅ Вывод: 2xx = «успешно», но с чёткой детализацией.
Проблема → решение
Проблема: если везде отдавать 200, клиент не понимает: ресурс создан, обновлён, удалён или ещё обрабатывается.
Решение: использовать разные 2xx + правильные заголовки и тело.
Решение: использовать разные 2xx + правильные заголовки и тело.
✅ Вывод: точный 2xx делает API предсказуемым и удобным для клиента.
Чем помогает и как работает
2xx‑коды показывают, что запрос выполнен успешно, но с разными результатами.
Это помогает клиенту правильно интерпретировать ответ.
Как это работает:
- Сервер выполняет действие.
- Выбирает подходящий код (200/201/202/204/206).
- Клиент читает код и понимает, что делать дальше.
✅ Вывод: правильный 2xx‑код = ясный успешный результат для клиента.
Ключевые термины (простыми словами)
- 2xx — ответы об успехе.
- Body (тело ответа) — данные, которые вернул сервер.
- Header (заголовок) — служебная информация о ответе.
- Location — ссылка на созданный ресурс.
- Retry-After — когда повторить запрос.
- Content-Range — диапазон возвращённых данных.
- ETag / Cache-Control — метки для кеша.
✅ Вывод: эти термины помогают понимать, что именно вернул сервер и как с этим работать.
Самое важное (must‑know)
- 201 должен быть с телом + Location — клиенту нужен и объект, и его URL.
- 204 — строго без тела (иначе это уже 200).
- 202 — только для асинхронных задач (когда результат ещё не готов).
- 206 — всегда с Content-Range (иначе клиент не понимает, что получил).
- Content-Type обязателен почти всегда (кроме 204).
✅ Вывод: эти пункты — база, без них API будет «ломаться» у клиентов.
1. 200 OK — «успех + данные»
Назначение: вернуть ресурс или результат запроса.
Простыми словами: сервер отдал данные, которые вы запрашивали.
Аналогия: вы показали билет и получили место в вагоне.
Простыми словами: сервер отдал данные, которые вы запрашивали.
Аналогия: вы показали билет и получили место в вагоне.
Пример:
HTTP/1.1 200 OKContent-Type: application/jsonETag: "c-1024" { "id": 10, "title": "JavaScript основы", "level": "beginner"}🔎 Как это происходит на практике:
- Клиент делает
GET /courses. - Сервер возвращает
200 OKи тело с данными. - Клиент отображает список или детали ресурса.
Характеристики:
- ✅ обычно есть тело (данные ресурса);
- ✅ Content-Type обязателен, если есть тело;
- ✅ ETag/Cache-Control полезны для кеширования.
⚠️ Важно: 200 может приходить без тела — это допустимо, но не рекомендуется. Если тело не нужно, лучше вернуть 204 No Content.
Когда использовать: чтение, поиск, фильтрация.
✅ Вывод: 200 = «успех, обычно с данными».
✅ Вывод: 200 = «успех, обычно с данными».
2. 201 Created — «ресурс создан»
Назначение: подтверждает создание нового объекта.
Простыми словами: объект создан, и вы сразу получаете его данные и адрес.
Аналогия: вы сделали заказ и получили номер брони.
Простыми словами: объект создан, и вы сразу получаете его данные и адрес.
Аналогия: вы сделали заказ и получили номер брони.
Пример:
HTTP/1.1 201 CreatedLocation: /courses/123Content-Type: application/json { "id": 123, "title": "React основы", "level": "beginner"}🔎 Как это происходит на практике:
- Клиент отправляет
POST /coursesс данными. - Сервер создаёт ресурс и отвечает
201 Created. - В ответе есть
Locationи тело созданного объекта.
Характеристики:
- ✅ тело обязательно (возвращаем созданный объект);
- ✅ Location обязателен — URL ресурса;
- ✅ используется с POST.
Когда использовать: создание записи, оформление заказа, регистрация.
✅ Вывод: 201 = «создано и доступно по ссылке».
✅ Вывод: 201 = «создано и доступно по ссылке».
3. 202 Accepted — «принято, но обрабатывается»
Назначение: запрос принят, результат будет позже.
Простыми словами: операция в очереди, итог нужно проверить позже.
Аналогия: вы сдали документы, но проверка ещё идёт.
Простыми словами: операция в очереди, итог нужно проверить позже.
Аналогия: вы сдали документы, но проверка ещё идёт.
Пример:
HTTP/1.1 202 AcceptedLocation: /operations/987Retry-After: 30Content-Type: application/json { "operationId": 987, "status": "processing"}🔎 Как это происходит на практике:
- Клиент запускает долгую операцию (например, отчёт).
- Сервер отвечает
202 Acceptedи даёт ссылку на статус. - Клиент проверяет статус или ждёт завершения.
Характеристики:
- ✅ тело может быть (ID операции);
- ✅ Location указывает на статус;
- ✅ Retry-After подсказывает, когда проверять.
Когда использовать: длительные операции, импорт, генерация отчётов.
✅ Вывод: 202 = «успех принятия, но не завершения».
✅ Вывод: 202 = «успех принятия, но не завершения».
4. 204 No Content — «успех без тела»
Назначение: действие выполнено, но возвращать нечего.
Простыми словами: всё ок, но данных для ответа нет.
Аналогия: отметка «всё сделано» без дополнительных вложений.
Простыми словами: всё ок, но данных для ответа нет.
Аналогия: отметка «всё сделано» без дополнительных вложений.
Пример:
HTTP/1.1 204 No Content🔎 Как это происходит на практике:
- Клиент делает
DELETE /courses/10. - Сервер удаляет ресурс и отвечает
204 No Content. - Клиент получает подтверждение без тела ответа.
Характеристики:
- ✅ тела нет и не должно быть;
- ✅ идеально для удаления.
Когда использовать: DELETE, подтверждение пустых изменений.
✅ Вывод: 204 = «успех, но данных нет».
✅ Вывод: 204 = «успех, но данных нет».
5. 206 Partial Content — «частичный ответ»
Назначение: вернуть часть большого ресурса.
Простыми словами: сервер отправил только кусок данных, который вы просили.
Аналогия: вы попросили одну главу книги, а не всю книгу.
Простыми словами: сервер отправил только кусок данных, который вы просили.
Аналогия: вы попросили одну главу книги, а не всю книгу.
Пример:
HTTP/1.1 206 Partial ContentAccept-Ranges: bytesContent-Range: bytes 0-499/1234Content-Type: application/octet-stream🔎 Как это происходит на практике:
- Клиент запрашивает диапазон:
Range: bytes=0-1023. - Сервер отвечает
206 Partial ContentиContent-Range. - Клиент получает часть файла и может докачивать дальше.
Характеристики:
- ✅ тело содержит только кусок;
- ✅ Content-Range обязателен;
- ✅ Accept-Ranges показывает поддержку диапазонов.
Когда использовать: видео, большие файлы, докачка.
✅ Вывод: 206 = «часть ресурса по запросу».
✅ Вывод: 206 = «часть ресурса по запросу».
6. 207 Multi-Status — «несколько статусов в одном ответе»
Назначение: вернуть результат по каждому элементу в пакетной операции.
Простыми словами: один запрос — много мини‑результатов по каждому элементу.
Аналогия: ведомость с оценками по каждому студенту.
Простыми словами: один запрос — много мини‑результатов по каждому элементу.
Аналогия: ведомость с оценками по каждому студенту.
Пример (упрощённо):
HTTP/1.1 207 Multi-StatusContent-Type: application/json { "results": [ { "id": 1, "status": 200 }, { "id": 2, "status": 404 } ]}🔎 Как это происходит на практике:
- Клиент отправляет batch‑запрос.
- Сервер обрабатывает элементы и формирует
207 Multi‑Status. - В теле ответа — статусы по каждому элементу.
Характеристики:
- ✅ тело обязательно (список статусов по элементам);
- ✅ используется для batch/массовых операций;
- ❗ пришёл из WebDAV, но встречается в практических API.
Когда использовать: массовые обновления, импорты, batch‑операции.
✅ Вывод: 207 = «успех операции, но статусы разные по элементам».
✅ Вывод: 207 = «успех операции, но статусы разные по элементам».
Сравнение 2xx (что возвращаем)
| Код | Смысл | Тело | Ключевые заголовки |
|---|---|---|---|
| 200 | успех + данные | ✅ да | Content-Type, ETag |
| 201 | создан ресурс | ✅ да | Location |
| 202 | принято | ✅ возможно | Location, Retry-After |
| 204 | успех без тела | ❌ нет | (без payload) |
| 206 | часть данных | ✅ да | Content-Range, Accept-Ranges |
| 207 | мульти‑статус | ✅ да | Content-Type |
✅ Вывод: выбор кода зависит от того, есть ли тело и завершено ли действие.
Часто спрашивают на собеседованиях
- 200 vs 204? 200 — есть тело, 204 — тела нет.
- 201 vs 200? 201 — ресурс создан, 200 — просто успешный ответ.
- Когда нужен Location? при создании (201) и часто при 202.
- Нужно ли тело в 201? да, это лучший и ожидаемый вариант для клиента.
- Можно ли тело в 204? нет, это нарушение стандарта.
- Зачем Content-Range? чтобы клиент понимал, какой кусок получил.
- 202 — это успех? да, но успех принятия, а не завершения.
- Когда использовать 207? при batch‑операциях, где у элементов разные статусы.
✅ Вывод: 2xx — это не «один код», а язык точных статусов.
Типичные ошибки
Ошибка 1: 200 вместо 201
❌ Неправильно: создать ресурс и вернуть 200.
✅ Правильно: 201 + Location.
Почему: клиенту нужен адрес нового объекта.
Практический пример:
✅ Правильно: 201 + Location.
Почему: клиенту нужен адрес нового объекта.
Практический пример:
POST /courses -> 201 Created + LocationОшибка 2: 204 с телом
❌ Неправильно: 204 + JSON.
✅ Правильно: 204 без тела или 200 с телом.
Почему: 204 запрещает payload.
Практический пример:
✅ Правильно: 204 без тела или 200 с телом.
Почему: 204 запрещает payload.
Практический пример:
DELETE /courses/10 -> 204 No ContentОшибка 3: 202 для мгновенной операции
❌ Неправильно: 202, когда всё уже готово.
✅ Правильно: 200 или 201.
Почему: 202 говорит «ещё в процессе».
Практический пример:
✅ Правильно: 200 или 201.
Почему: 202 говорит «ещё в процессе».
Практический пример:
POST /report -> 200 OK (если отчёт уже готов)Ошибка 4: 206 без Content-Range
❌ Неправильно: 206 без диапазона.
✅ Правильно: 206 + Content-Range.
Почему: клиент не знает, какую часть получил.
Практический пример:
✅ Правильно: 206 + Content-Range.
Почему: клиент не знает, какую часть получил.
Практический пример:
GET /video -> 206 Partial Content + Content-RangeОшибка 5: нет Content-Type
❌ Неправильно: 200 без указания формата.
✅ Правильно: всегда ставить Content-Type.
Почему: клиент не поймёт, как парсить ответ.
Практический пример:
✅ Правильно: всегда ставить Content-Type.
Почему: клиент не поймёт, как парсить ответ.
Практический пример:
HTTP/1.1 200 OKContent-Type: application/jsonОшибка 6: 201 без тела и без Location
❌ Неправильно: «создали», но ничего не дали.
✅ Правильно: вернуть тело + Location.
Почему: клиенту нужен адрес ресурса.
Практический пример:
✅ Правильно: вернуть тело + Location.
Почему: клиенту нужен адрес ресурса.
Практический пример:
HTTP/1.1 201 CreatedLocation: /users/45Best Practices
- Используйте 201 для создания, а не 200.
- Для 201 возвращайте тело + Location.
- Для удаления — 204 без тела.
- Для асинхронных задач — 202 + ссылка на статус.
- Для частичных данных — 206 + Content-Range.
- Для batch‑операций — 207 + список статусов.
- Всегда указывайте Content-Type.
- Если ресурс создан — обязательно дайте Location.
Заключение
🚀 2xx — это не «один успех», а целая палитра результатов.
📌 Правильный код = понятный сценарий для клиента.
🧭 Заголовки и тело помогают правильно прочитать результат.
📌 Правильный код = понятный сценарий для клиента.
🧭 Заголовки и тело помогают правильно прочитать результат.
Теперь ты можешь говорить с клиентом на языке статусов так, как это делают сильные API‑команды.
Ты уже умеешь строить предсказуемые ответы — осталось только применять это в проектах.
Ты уже умеешь строить предсказуемые ответы — осталось только применять это в проектах.