Какие статусы HTTP-ответов вы знаете?

Ответ

В работе с веб-приложениями я постоянно имею дело с 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. Это пиздец как неправильно. Клиент же не поймёт, это он накосячил или у тебя сервер сгорел.