Коды состояния HTTP

Искомая таблица всех зарегистрированных кодов состояния HTTP, их точных причинных фраз и разделов RFC, которые их определяют. Фильтрация по классам 1xx–5xx.

Что на самом деле означает этот код ответа? Введите число, например 429, или слово, например gateway, чтобы отфильтровать таблицу, либо сузьте её до одного класса. В каждой строке показаны код, точная причинная фраза, передаваемая по сети, и раздел спецификации, который её определяет.

Подходящие коды
Код Причинная фраза Определён в

Как правильно читать коды состояния HTTP

Цифра класса несёт в себе контракт

Каждый HTTP-ответ начинается с трёхзначного кода, и первая цифра — единственная часть, которую клиент обязан понимать. RFC 9110 прямо об этом говорит: клиент, получивший неизвестный 499, должен обрабатывать его точно так же, как 400, потому что класс определяет семантику, а оставшиеся две цифры лишь уточняют её. Именно это правило сохраняет расширяемость протокола. Прокси, написанный в 2005 году, всё ещё может правильно маршрутизировать 451, не зная, что такое юридическая цензура.

Пять классов чётко делятся по тому, кто отвечает за происходящее дальше. 1xx — это промежуточный ответ, поэтому настоящий ответ ещё идёт, а соединение остаётся открытым. 2xx означает, что запрос успешен и клиент может остановиться. 3xx возвращает перенаправление, поэтому клиент должен повторить попытку в другом месте. 4xx винит запрос, поэтому его повторение без изменений снова завершится неудачей. 5xx винит сервер, поэтому идентичный запрос при повторе может пройти. Вот почему логика повтора опирается на класс, а не на конкретный код: повторять 503 разумно, повторять 403 — это ошибка.

Коды, которые постоянно путают

Различие между 301 и 308 или 302 и 307 не стилистическое. Старая пара позволяет клиенту переписать POST в GET при следовании перенаправлению, что браузеры исторически делали. Новая пара запрещает такую перезапись и сохраняет и метод, и тело. Если вы перенесёте конечную точку формы с помощью 301, некоторые клиенты молча преобразуют отправку в GET и потеряют полезную нагрузку. Используйте 308 или 307 для всего, что не идемпотентно.

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

Класс 4xx также содержит действительно полезную пару: 400 против 422. 400 означает, что запрос вообще не удалось разобрать, то есть синтаксис сломан. 422 означает, что синтаксис разобрался нормально, но содержимое не прошло валидацию. Разделение этих двух превращает непрозрачную ошибку в понятную для клиентов API.

Причинные фразы — только для людей

Текст рядом с кодом, например Not Found или I'm a teapot, — это причинная фраза. HTTP/1.1 передаёт её в строке состояния, но HTTP/2 и HTTP/3 удалили её полностью, поэтому современное соединение часто несёт только число без фразы. Ничто в клиенте не должно ветвиться по этой строке. Она существует, чтобы человек, читающий лог или сырой трассировку, видел, что произошло, без таблицы соответствий.

Некоторые коды также более ограничены, чем кажется. 204 и 304 не должны содержать тело сообщения, поэтому посредник, добавляющий его, создаёт неверный ответ. Ответ HEAD никогда не несёт тела независимо от кода. Эти правила фрейминга важны, потому что тело там, где его не ждут, рассинхронизирует повторное использование соединения, что проявляется как странная межзапросовая порча, а не как очевидная ошибка.

Примечание об открытом коде: реализовано на чистом JavaScript без сторонних библиотек.

Часто задаваемые вопросы

Сколько существует кодов состояния HTTP?
IANA перечисляет чуть больше шестидесяти зарегистрированных кодов во всех пяти классах, и эта таблица охватывает их все плюс несколько широко развёрнутых кодов WebDAV и расширений. Реестр намеренно открыт, поэтому могут добавляться новые коды — именно поэтому клиенты должны возвращаться к цифре класса для всего незнакомого.
Использовать 301 или 308 для постоянного перенаправления?
Используйте 308, если только вы специально не хотите, чтобы старые клиенты преобразовывали POST в GET. Оба означают, что ресурс перемещён навсегда, но только 308 гарантирует сохранение метода и тела при перенаправлении. Для простого переноса страницы подходит любой, и 301 имеет чуть более широкую устаревшую поддержку.
В чём разница между 401 и 403?
401 означает, что вы не аутентифицированы, и ответ должен содержать заголовок WWW-Authenticate, описывающий как. 403 означает, что вы аутентифицированы нормально, но всё равно не имеете доступа. Если пользователю просто нужно войти — правильный 401; если у его учётной записи действительно нет прав — правильный 403.
Является ли 418 I'm a teapot настоящим кодом состояния?
Он настоящий в том смысле, что RFC 2324 определяет его для Hyper Text Coffee Pot Control Protocol — первоапрельской спецификации 1998 года. IANA сохраняет его зарезервированным, чтобы ничто другое не могло занять 418. Он не является частью HTTP как такового, но несколько фреймворков реализуют его как пасхалку.
Какие коды мой клиент должен повторять автоматически?
Повторяйте при 408, 429 и большинстве ответов 5xx и всегда уважайте заголовок Retry-After, когда он присутствует. Не повторяйте коды 4xx, кроме 408 и 429, потому что проблема в самом запросе, и его повторение без изменений завершится неудачей так же.
Почему в моём ответе HTTP/2 нет причинной фразы?
HTTP/2 и HTTP/3 убрали причинную фразу из проводного формата, потому что ни один клиент не должен был её разбирать. Передаётся только числовой код. Инструменты, показывающие фразу для ответа HTTP/2, ищут её локально в таблице вроде этой.