сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · FastAPI, Django и API

Семантика HTTP

HTTP-семантика: методы и коды не для галочки

HTTP-коды и методы это контракт, по которому клиент решает: ретраить или нет, идти логиниться или это бесполезно, битый у него запрос или недопустимое значение. Собес гоняет по границам, которые все путают: 401 против 403, 400 против 422, PUT против PATCH - потому что ошибка тут даёт реальные баги в интеграциях.

Типовые формулировки: «чем 401 отличается от 403?», «PUT или PATCH?», «какой код на невалидное значение поля».

Методы, идемпотентность и ретраи

GET - безопасное чтение, POST - создать или выполнить действие, PUT - заменить целиком, DELETE - удалить. GET и HEAD безопасны - не меняют состояние. Ключевое свойство для ретраев - идемпотентность: PUT и DELETE идемпотентны (повтор даёт то же состояние), POST - нет: два POST /orders создадут два заказа.

Отсюда практика: ретраить сетевой сбой безопасно для GET/PUT/DELETE, а для POST - только с защитой от задвоения (см. Idempotency-Key). PUT заменяет ресурс ЦЕЛИКОМ, поэтому неполное тело затрёт непереданные поля; PATCH меняет только указанные и идемпотентен не гарантированно.

// Классы кодов: 2xx успех, 4xx вина клиента, 5xx сбой сервера - по ним понимают, кто виноват и стоит ли повторять.

идемпотентность
повтор запроса не меняет итог против одного вызова
PUT vs PATCH
полная замена против частичного обновления

Коды-двойники: 401/403 и 400/422

401 и 403 - разные вещи. 401 - не аутентифицирован: токена нет или он просрочен, клиент должен пойти обновить токен и повторить. 403 - аутентифицирован, но прав нет: логиниться заново бесполезно, ответ не изменится. Путаница ломает клиентскую логику: по 401 клиент рефрешит токен, по 403 - не должен.

400 и 422 тоже про разное. 400 - запрос синтаксически битый (невалидный JSON, кривой формат). А валидный JSON с недопустимым значением, скажем age=-5, точнее описывает 422 Unprocessable Entity - его и отдают FastAPI и DRF (Django REST Framework) при ошибке валидации схемы.

// Отдавать 200 с телом ошибки вместо 4xx - маскировать проблему: клиент считает запрос успешным.

401 vs 403
не аутентифицирован против нет прав
400 vs 422
битый синтаксис против валидного, но недопустимого

Как отвечать: «Чем 401 отличается от 403?»

401 это про аутентификацию: сервер не знает, кто ты, потому что токена нет или он просрочен. Клиент на 401 должен пойти получить или обновить токен и повторить запрос. 403 - про авторизацию: личность установлена, но конкретно этих прав у тебя нет - например, обычный юзер лезет в админский эндпоинт. Повторять логин тут бессмысленно, ответ не изменится, пока не выдадут права. Практический смысл в том, что клиентская логика на них реагирует по-разному: 401 запускает рефреш токена, а 403 это стоп, показать «нет доступа».

Разведены аутентификация и авторизация с конкретной реакцией клиента на каждый код - видно, что человек понимает последствия для интеграции, а не только определения.

На чём валят

  • PUT неполным телом затрёт непереданные поля - он заменяет ресурс целиком; для частичного нужен PATCH.
  • Отдавать 200 с телом ошибки вместо 4xx - маскировка проблемы от клиента и прокси.
  • Путать 401 и 403: клиент по 401 обновит токен, а по 403 это бессмысленно.
  • Слать 400 на валидный JSON с недопустимым значением - точнее 422; и наоборот.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.

  1. #http_semantics1 / 5
    Что означают классы кодов 2xx, 4xx и 5xx?
    A)Информация, редирект и успех — по возрастанию номера класса
    B)Кэшируемый, некэшируемый и потоковый ответ соответственно
    C)Все три — разновидности успешного ответа с разным телом
    D)Успех, ошибка клиента и ошибка сервера соответственно
    показать ответ и разбор
    +D)Успех, ошибка клиента и ошибка сервера соответственно

    // разбор: 2xx — успех (200 OK, 201 Created, 204 No Content), 4xx — ошибка на стороне клиента (400 плохой запрос, 404 не найдено, 401/403 доступ), 5xx — сбой на сервере (500, 502, 503). Разделение 4xx/5xx важно: по нему понимают, кто виноват и стоит ли ретраить.

  2. #http_semantics2 / 5
    Чем PUT отличается от POST по идемпотентности?
    A)PUT идемпотентен: повтор даёт то же состояние; POST — нет
    B)Оба идемпотентны, поэтому их можно повторять сколько угодно
    C)POST идемпотентен, а PUT при повторе создаёт дубликаты ресурса
    D)Идемпотентность зависит только от базы, а не от самого метода
    показать ответ и разбор
    +A)PUT идемпотентен: повтор даёт то же состояние; POST — нет

    // разбор: PUT идемпотентен: повтор одного и того же PUT приводит ресурс к тому же состоянию (заменяет целиком). POST не идемпотентен — два POST /orders создадут два заказа. Отсюда практика: ретраи безопасны для PUT/DELETE/GET, а для POST нужен ключ идемпотентности.

  3. #http_semantics3 / 5
    Когда вернуть 401, а когда 403?
    A)401 — сервер упал, 403 — ресурс временно недоступен клиенту
    B)401 — ресурс не найден, 403 — неверный формат тела запроса
    C)401 и 403 взаимозаменяемы, разница только в тексте сообщения
    D)401 — не аутентифицирован, 403 — прав не хватает
    показать ответ и разбор
    +D)401 — не аутентифицирован, 403 — прав не хватает

    // разбор: 401 Unauthorized (по факту «не аутентифицирован») — личность не установлена: нет/просрочен токен. 403 Forbidden — личность известна, но прав на действие нет. Практическое следствие: на 401 клиент идёт логиниться/обновлять токен, на 403 — это бесполезно.

  4. #http_semantics4 / 5
    Тело запроса — валидный JSON, но поле age = -5 (недопустимо). Какой код точнее?
    A)200 с телом ошибки, чтобы не пугать клиента кодом четвёртой сотни
    B)500, ведь сервер не смог обработать присланное значение поля
    C)400, потому что проблема входа — это Bad Request
    D)422: синтаксис верен, но данные не проходят по смыслу
    показать ответ и разбор
    +D)422: синтаксис верен, но данные не проходят по смыслу

    // разбор: 400 Bad Request — про синтаксически битый запрос (не распарсился). Если JSON корректен, но нарушает правила (отрицательный возраст) — точнее 422 Unprocessable Entity; именно его FastAPI/DRF отдают на ошибки валидации. 5xx тут ни при чём — виноват клиент, не сервер.

  5. #http_semantics5 / 5
    Чем PATCH отличается от PUT?
    A)PATCH работает лишь с коллекциями, а PUT — с элементами
    B)Разницы нет, PATCH — просто новое имя для метода PUT сегодня
    C)PATCH меняет часть полей, PUT заменяет ресурс целиком
    D)PATCH только читает изменённые поля, а PUT их записывает
    показать ответ и разбор
    +C)PATCH меняет часть полей, PUT заменяет ресурс целиком

    // разбор: PUT заменяет ресурс целиком — не переданные поля обнулятся/сбросятся к дефолту. PATCH меняет только указанные поля, оставляя прочие как есть. PUT идемпотентен по определению; PATCH может быть идемпотентным или нет — зависит от формата патча.

дальше

Теорию прочитали. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.