Ответ
В работе с веб-приложениями я постоянно имею дело с HTTP-статусами. Они сгруппированы в классы по первой цифре трехзначного кода. Правильное использование статусов критически важно для RESTful API и понимания клиентом результата его запроса.
Основные классы и часто используемые коды:
| Класс | Значение | Ключевые примеры |
|---|---|---|
| 1xx (Информационные) | Запрос принят, процесс продолжается. | 100 Continue (сервер готов принять тело запроса). Встречается редко. |
| 2xx (Успех) | Запрос успешно обработан. | 200 OK – стандартный ответ для успешных GET, PUT, PATCH.201 Created – ресурс создан (успешный POST). В ответе должен быть заголовок Location с URI нового ресурса.204 No Content – сервер успешно обработал запрос, но не возвращает тело (успешный DELETE, иногда POST/PUT). |
| 3xx (Перенаправление) | Для завершения запроса требуется дополнительное действие (обычно – ещё один запрос). | 301 Moved Permanently – URI ресурса изменился навсегда. Все последующие запросы должны использовать новый URI.302 Found – временное перенаправление. Клиент должен использовать исходный URI для будущих запросов.304 Not Modified – ответ на условный GET (If-Modified-Since), указывает, что ресурс не изменился. Клиент может использовать кешированную версию. |
| 4xx (Ошибка клиента) | Запрос содержит ошибку (неверный синтаксис, невалидные данные, недостаточно прав). | 400 Bad Request – общая ошибка, сервер не может понять запрос (например, невалидный JSON).401 Unauthorized – требуется аутентификация (клиент не представил учётные данные).403 Forbidden – сервер понял запрос, но отказывается его авторизовать (прав недостаточно).404 Not Found – ресурс по указанному URI не найден.422 Unprocessable Entity (WebDAV) – запрос синтаксически верен, но содержит семантические ошибки (например, не пройдена валидация полей). Часто используется в API. |
| 5xx (Ошибка сервера) | Сервер не смог выполнить запрос из-за внутренней ошибки. | 500 Internal Server Error – общая ошибка сервера, когда более конкретный код 5xx не подходит.502 Bad Gateway – сервер, выступая в роли шлюза или прокси, получил неверный ответ от вышестоящего сервера.503 Service Unavailable – сервер временно не может обрабатывать запросы (перегрузка, техобслуживание). Должен включать заголовок Retry-After. |
Практический пример из моего опыта (Python/Flask API):
from flask import jsonify, abort
@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = db_session.query(User).get(user_id)
if user is None:
# Клиент запросил несуществующий ресурс
abort(404, description="User not found")
# Или можно вернуть JSON:
# return jsonify({"error": "User not found"}), 404
if not current_user.has_permission('view', user):
# У клиента нет прав на просмотр этого ресурса
abort(403)
# Успешный ответ
return jsonify(user.to_dict()), 200
@app.route('/api/users', methods=['POST'])
def create_user():
data = request.get_json()
if not data:
abort(400, description="No JSON data provided")
# ... валидация данных ...
if validation_errors:
# Данные не прошли бизнес-валидацию
return jsonify({"errors": validation_errors}), 422
new_user = User(**data)
db_session.add(new_user)
db_session.commit()
# Ресурс создан, возвращаем его данные и статус 201
return jsonify(new_user.to_dict()), 201 Ответ 18+ 🔞
А, слушай, про эти ваши HTTP-статусы я могу рассказывать часами, ёпта. Это ж основа основ, без них в вебе — как без рук. Представь, ты в бар заходишь, кричишь: «Дайте пива!» А тебе в ответ — молчание. Или пиздюлину. Вот примерно так и клиент себя чувствует, когда сервер ему нихуя не отвечает или отвечает какой-то хуйнёй. А статусы — это как понятный язык: «окей», «иди нахуй», «плати сначала» или «ой, всё».
Короче, смотри, они все по первой цифре разбиты. Как будто классы в школе, только вместо двоечников и отличников — у тебя информационные, успешные и прочие пиздецы.
1xx — Информационные. Это типа «я тебя услышал, чувак, погоди чутка». Самый известный — 100 Continue. Это когда клиент спрашивает: «Можно я тебе сейчас овердохуища данных в запросе вывалю?» А сервер такой: «Давай, я готов, хули». В жизни встречается редко, как честный политик.
2xx — Успех. Вот это любовь. Запрос прошёл, всё заебись.
200 OK— классика. Всё норм, держи что просил. Для GET, PUT, PATCH.201 Created— это когда ты что-то создал (POST, например, нового юзера). Идеальный ответ должен быть с заголовкомLocation, где адрес этой новинки. Типа «вот, родил, полюбуйся».204 No Content— сделал дело, но хвастаться нечем. Удалил что-то (DELETE) — и молчи в тряпочку. Тела ответа нет.
3xx — Перенаправления. Сервер такой хитрая жопа: «Не здесь, иди туда».
301 Moved Permanently— переехал навсегда. Все закладки обновляй, ссылки меняй. Навсегда — это навсегда.302 Found— временный переезд. «Я тут, но ненадолго, потом обратно вернусь, так что старый адрес не теряй».304 Not Modified— магия кеширования. Клиент спрашивает: «А что изменилось с прошлого раза?» Сервер: «Ни хуя себе, всё так же». Бери из кеша и не грузи меня.
4xx — Ошибка клиента. Это когда клиент — распиздяй. Запрос кривой, не туда попал, прав нет.
400 Bad Request— общая помойка. «Чё-то ты мне какую-то дичь прислал, я даже понять не могу». Невалидный JSON — классика.401 Unauthorized— «А ты кто такой? Давай, предъяви логин-пароль». Нет учётных данных — иди нахуй.403 Forbidden— «Я-то тебя узнал, но ты сюда не пройдёшь». Прав не хватает. Доверия ебать ноль.404 Not Found— легенда интернета. «То, что ты ищешь, хуй с горы. Нету его».422 Unprocessable Entity— любимчик в API. Запрос вроде правильный, синтаксис ок, но логика — пиздец. Не прошла валидация полей, например. «Данные-то ты отправил, но они бредовые».
5xx — Ошибка сервера. А вот это уже наш, серверный, косяк. Стыдно, но бывает. Тут уже волнение ебать у клиента.
500 Internal Server Error— классика жанра. «Что-то пошло не так, а что — хрен его знает». Упал код, исключение не поймали.502 Bad Gateway— когда твой сервер — просто посредник, а тот, к кому он лезет, накрылся медным тазом. Прокси/гейтвей получил хуйню вместо ответа.503 Service Unavailable— «Ребят, я перегружен/на техобслуживании, зайдите позже». Хороший тон — ещё иRetry-Afterзаголовок приложить, чтоб знали, когда вернуться.
Вот тебе живой пример из моего кода на Flask, чтоб не на пальцах:
from flask import jsonify, abort
@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = db_session.query(User).get(user_id)
if user is None:
# Клиент просит того, чего нет. Чистой воды 404.
abort(404, description="User not found")
# Или можно так, если любишь JSON:
# return jsonify({"error": "User not found"}), 404
if not current_user.has_permission('view', user):
# Аутентифицировался, но лезет не в свои дела. 403, запрещено.
abort(403)
# Всё чики-пуки, отдаём юзера и статус 200.
return jsonify(user.to_dict()), 200
@app.route('/api/users', methods=['POST'])
def create_user():
data = request.get_json()
if not data:
# Прислал пустой запрос или не JSON. 400, иди учи матчасть.
abort(400, description="No JSON data provided")
# ... тут какая-то валидация данных ...
if validation_errors:
# Данные вроде как JSON, но бредовые (email кривой, пароль слабый).
# Вот он, наш красавец 422!
return jsonify({"errors": validation_errors}), 422
new_user = User(**data)
db_session.add(new_user)
db_session.commit()
# Всё создалось! Возвращаем нового юзера и гордый статус 201.
return jsonify(new_user.to_dict()), 201
Вот и вся магия. Главное — не быть мудаком и отправлять клиенту тот статус, который реально отражает суть происходящего. А то ведь бывает, что ошибка бизнес-логики — а в ответе 500. Это пиздец как неправильно. Клиент же не поймёт, это он накосячил или у тебя сервер сгорел.