Что такое HTTP коды ответов и их группы
Что проверяют
Понимаете ли вы, что статус ответа это часть контракта, а не украшение. От питониста ждут двух вещей сразу: что он правильно отдаёт коды из своего сервиса и правильно разбирает чужие в клиентском коде.
Как отвечать
Пять групп по первой цифре: 1xx промежуточные, 2xx успех, 3xx перенаправление, 4xx ошибка на стороне клиента (запрос надо менять), 5xx сбой на стороне сервера (запрос можно повторить). Дальше полезно назвать рабочий минимум: 200, 201 с заголовком Location, 204 без тела, 301 и 302, 307 и 308, 400, 401, 403, 404, 409, 422, 429 с Retry-After, 500, 502, 503, 504.
Разница 401 и 403: первый про «не знаю, кто ты», второй про «знаю и не разрешаю». Разница пар редиректа: старая исторически позволяет клиенту сменить метод на GET и потерять тело, новая сохраняет и метод, и тело, поэтому перенос POST описывают через 307 или 308.
r = requests.post(url, json=payload, timeout=5)
if r.status_code == 429:
time.sleep(float(r.headers.get("Retry-After", 1)))
r.raise_for_status()Где спотыкаются
Отдают 200 с ошибкой внутри тела. Клиент, мониторинг и балансировщик считают такой ответ успешным, деградация не видна на графиках, а ретраи и переключение на резерв не срабатывают.
Забывают, что клиентская библиотека сама по себе не бросает исключение на 4xx и 5xx: без явной проверки статуса код разбирает тело ошибки как нормальный ответ. Редиректы при этом проходятся автоматически, и итоговый статус уже не тот, что вернул первый адрес.
Валят в 500 всё подряд, включая невалидный ввод и нарушение бизнес-правила. Клиент по 5xx честно повторяет запрос, и сервис получает поток ретраев на том, что никогда не станет корректным.