ОШИБКА С КОДОМ 409

Время на прочтение


ОШИБКА С КОДОМ 409

Если вы не специалист по REST, то, вероятно, в своих ответах постоянно используете одни и те же HTTP-коды, в основном 200, 404 и 500. Если применяется аутентификация, то, возможно, добавляются 401 и 403; если есть переадресации, то 301 и 302, но на этом, скорее всего, список заканчивается. Но спектр возможных кодов состояний гораздо шире и он может сильно улучшить семантику. Хотя во многих обсуждениях REST упор делается на сущностях и методах, применение подходящих кодов ответов о состояниях может повысить удобство вашего API.

Код состояния HTTP (англ. HTTP status code) — часть первой строки ответа сервера при запросах по протоколу HTTP.
Он представляет собой целое трёхразрядное десятичное число. Первая цифра указывает на класс состояния. За кодом ответа обычно следует отделённая пробелом поясняющая фраза на английском языке, которая разъясняет человеку причину именно такого ответа. Примеры:

Клиент может не знать все коды состояния, но он обязан отреагировать в соответствии с классом кода. В настоящее время выделено пять классов кодов состояния.

Веб-сервер Internet Information Services в своих файлах журналов, кроме стандартных кодов состояния, использует подкоды, записывая их через точку после основного. При этом в ответах от сервера данный подкод не размещается — он нужен администратору сервера, чтобы тот мог более точно определять источники проблем.

Ситуацию с использованием кодов ответов HTTP можно заносить в палату мер и весов: вот что происходит, когда благие намерения разработчиков спецификации сталкиваются с жестокой реальностью. Даже с двумя жестокими реальностями.

Как мы обсудили в Главе 10, одна из целей существования семантических ошибок — помочь клиенту понять, что стало причиной ошибки. При разработке спецификации HTTP (в частности, RFC 7231) эта цель очевидно была одной из главных. Более того, архитектурные ограничения REST, как их описал Фьелдинг в своей диссертации, предполагают, что не только клиенты должны понимать семантику ошибки, но и все сетевые агенты (прокси) между клиентом и сервером в «многослойной» архитектуре. И, в соответствии с этим, номенклатура статус-кодов HTTP действительно весьма подробно описывает почти любые проблемы, которые могут случиться с HTTP-запросом: недопустимые значения Accept-*-заголовков, отсутствующий Content-Length, неподдерживаемый HTTP-метод, слишком длинный URI и так далее.

Но вот с чем RFC совершенно не помогает — это с вопросом, а что собственно клиенту или прокси делать с ошибкой. Как мы обсуждали, ошибки могут быть устранимыми или неустранимыми. Если ошибки неустранимая, то клиентам по большому счёту наплевать на всю эту петрушку со статус-кодами и заголовками, а уж промежуточным прокси тем более. Для этого на самом деле трёх кодов было бы достаточно:

Замечание: кстати, обратите внимание на проблему дизайна спецификации. По умолчанию все 4xx коды не кэшируются, за исключением: 404, 405, 410, 414. Мы не сомневаемся, что это было сделано из благих намерений, но подозреваем, что количество людей, знающих об этой тонкости, примерно равно количеству редакторов спецификации. В результате мы имеем множество ситуаций (автор лично разгребал последствия одной из них), когда 404-ки были возвращены ошибочно, но клиент их закэшировал, тем самым продлив факап на неопределённое время.

Что касается устранимых проблем — то да, статус-коды в чем-то помогают. Некоторые из них вполне конкретны, например 411 Length Required. А некоторые — нет. Можно привести множество ситуаций, где под одним кодом прячутся разнородные ошибки:

Таким образом, мы вполне естественным образом приходим к идее отдавать детальное описание ошибки в заголовках и/или теле ответа, не пытаясь изобрести новый код для каждой ситуации — абсолютно очевидно, что нельзя задизайнить по ошибке на каждый потенциально неправильный параметр вместо единой 400-ки, например.

Замечание: авторы спецификации тоже это понимали, и добавили следующую фразу: ‘The response message will usually contain a representation that explains the status’. Мы с ними, конечно, полностью согласны, но не можем не отметить, что эта фраза не только делает кусок спецификации бесполезным (а зачем нужны коды-то тогда?), но и противоречит парадигме REST: другие агенты в многоуровневой системе не могут понять, что же там «объясняет» представление ошибки, и сама ошибка становится для них непрозрачной.

Казалось бы, мы пришли к логичному выводу: используйте статус-коды для индикации «класса» ошибки в терминах протокола HTTP, а детали положите в ответ. Но вот тут теория повторно на всех парах напарывается на практику. С самого появления Web все фреймворки и серверное ПО полагаются на статус-коды для логирования и построения мониторингов. Я не думаю, что сильно совру, если скажу, что буквально не существует платформы, которая из коробки умеет строить графики по семантическим данным в ответе ошибки, а не по статус-кодам. И отсюда автоматически следует дальнейшее усугубление проблемы: чтобы отсечь в своих мониторингах незначимые ошибки и эскалировать значимые, разработчики начали попросту придумывать новые статус-коды — или использовать существующие не по назначению.

В современном мире мы буквально живём в этом бардаке: статус-коды HTTP используются вовсе не в целях поддержания чистоты протокола, а для графиков; их истинное значение забыто; клиенты обычно и не пытаются хоть какие-то выводы из кода ответа сделать, редуцируя его до первой цифры. ( Честно говоря, ещё неизвестно, что хуже — игнорировать код или, напротив, писать логику поверх кодов, использованных не по назначению.) Ну и, конечно, нельзя не упомянуть о широко распространённой практике отдавать ошибки внутри 200-ок.

Читайте также:  Код ошибки 8x8007007b windows 10

А какие ваши предложения?

На самом деле есть три подхода к решению этой ситуации:

Выбор за вами, но на всякий случай заметим, что подход #3 весьма дорог в реализации.

— Этот текст написан в рамках подготовки будущего раздела про HTTP API для моей книги, работы ведутся на Гитхабе.

Англоязычная версия этого же текста здесь.

Я буду признателен, если кто-то пошарит её на реддите, я сам по правилам реддита не могу.

HTTP response status codes indicate whether a specific HTTP request has been successfully completed.
Responses are grouped in five classes:

The status codes listed below are defined by RFC 9110.

Note: If you receive a response that is not in this list, it is a non-standard response, possibly custom to the server’s software.

Information responses

This interim response indicates that the client should continue the request or ignore the response if the request is already finished.

101 Switching Protocols

This code is sent in response to an Upgrade request header from the client and indicates the protocol the server is switching to.

102 Processing (WebDAV)

This code indicates that the server has received and is processing the request, but no response is available yet.

103 Early Hints

Successful responses

The request succeeded. The result meaning of “success” depends on the HTTP method:

The request succeeded, and a new resource was created as a result. This is typically the response sent after POST requests, or some PUT requests.

The request has been received but not yet acted upon.
It is noncommittal, since there is no way in HTTP to later send an asynchronous response indicating the outcome of the request.
It is intended for cases where another process or server handles the request, or for batch processing.

This response code means the returned metadata is not exactly the same as is available from the origin server, but is collected from a local or a third-party copy.
This is mostly used for mirrors or backups of another resource.
Except for that specific case, the 200 OK response is preferred to this status.

204 No Content

205 Reset Content

206 Partial Content

This response code is used when the Range header is sent from the client to request only part of a resource.

207 Multi-Status (WebDAV)

Conveys information about multiple resources, for situations where multiple status codes might be appropriate.

208 Already Reported (WebDAV)

226 IM Used (HTTP Delta encoding)

The server has fulfilled a GET request for the resource, and the response is a representation of the result of one or more instance-manipulations applied to the current instance.

Redirection messages

300 Multiple Choices

301 Moved Permanently

The URL of the requested resource has been changed permanently. The new URL is given in the response.

This response code means that the URI of requested resource has been changed temporarily.
Further changes in the URI might be made in the future. Therefore, this same URI should be used by the client in future requests.

303 See Other

The server sent this response to direct the client to get the requested resource at another URI with a GET request.

304 Не изменено

Используется для целей кэширования.
Он сообщает клиенту, что ответ не был изменен, поэтому клиент может продолжать использовать ту же кэшированную версию ответа.

305 Использовать прокси

Определено в предыдущей версии спецификации HTTP, чтобы указать, что запрошенный ответ должен быть доступен через прокси.
Он устарел из-за проблем безопасности, связанных с внутренней настройкой прокси-сервера.

Этот код ответа больше не используется; это просто зарезервировано. Он использовался в предыдущей версии спецификации HTTP/1.1.

307 Временное перенаправление

308 Постоянное перенаправление

400 Неверный запрос

Сервер не может или не будет обрабатывать запрос из-за чего-то, что воспринимается как ошибка клиента (например, неправильный синтаксис запроса, неверный кадр сообщения запроса или обманная маршрутизация запроса).

Хотя стандарт HTTP определяет «неавторизованный», семантически этот ответ означает «неаутентифицированный».
То есть клиент должен аутентифицировать себя, чтобы получить запрошенный ответ.

402 Требуется оплата

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

Клиент не имеет прав доступа к контенту; то есть он неавторизован, поэтому сервер отказывается предоставить запрошенный ресурс.
В отличие от 401 Unauthorized, личность клиента известна серверу.

404 Не найден

Сервер не может найти запрошенный ресурс.
В браузере это означает, что URL-адрес не распознан.
В API это также может означать, что конечная точка действительна, но сам ресурс не существует.
Серверы также могут отправить этот ответ вместо 403 Forbidden, чтобы скрыть существование ресурса от неавторизованного клиента.
Этот код ответа, вероятно, наиболее известен из-за его частого появления в сети.

Читайте также:  КОДЫ ОШИБОК ПО НА ТЕРМИНАЛАХ ВТБ

405 Метод не разрешен

Метод запроса известен серверу, но не поддерживается целевым ресурсом.
Например, API может не разрешать вызов DELETE для удаления ресурса.

406 Неприемлемо

407 Требуется аутентификация прокси

Это похоже на 401 Unauthorized, но аутентификация должна выполняться через прокси-сервер.

408 Тайм-аут запроса

Некоторые серверы отправляют этот ответ при незанятом соединении даже без предварительного запроса со стороны клиента.
Это означает, что сервер хотел бы закрыть это неиспользуемое соединение.
Этот ответ используется гораздо чаще, поскольку некоторые браузеры, такие как Chrome, Firefox 27+ или IE9, используют механизмы предварительного подключения HTTP для ускорения серфинга.
Также обратите внимание, что некоторые серверы просто отключают соединение, не отправляя это сообщение.

Этот ответ отправляется, когда запрос конфликтует с текущим состоянием сервера.

Этот ответ отправляется, когда запрошенный контент был окончательно удален с сервера без адреса пересылки.
Ожидается, что клиенты удалят свои кеши и ссылки на ресурс.
Спецификация HTTP предполагает, что этот код состояния будет использоваться для «ограниченных по времени рекламных услуг».
API не должны чувствовать себя обязанными указывать ресурсы, которые были удалены, с помощью этого кода состояния.

Сервер отклонил запрос, поскольку поле заголовка Content-Length не определено и оно требуется серверу.

412 Предварительное условие не выполнено

Клиент указал в своих заголовках предварительные условия, которым сервер не соответствует.

413 Слишком большая полезная нагрузка

Объект запроса превышает пределы, определенные сервером.
Сервер может закрыть соединение или вернуть поле заголовка Retry-After.

414 Слишком длинный URI

URI, запрошенный клиентом, длиннее, чем сервер готов интерпретировать.

415 Неподдерживаемый тип носителя

Медиа-формат запрошенных данных не поддерживается сервером, поэтому сервер отклоняет запрос.

416 Диапазон неудовлетворителен

Диапазон, указанный в поле заголовка Range в запросе, не может быть заполнен.
Возможно, диапазон выходит за пределы размера данных целевого URI.

417 Ожидание не оправдалось

Этот код ответа означает, что ожидание, указанное в поле заголовка запроса Expect, не может быть выполнено сервером.

418 Я чайник

Официант отклоняет попытку заварить кофе в чайнике.

421 Неверно направленный запрос

Запрос был направлен на сервер, который не может дать ответ.
Его может отправить сервер, который не настроен на выдачу ответов для комбинации схемы и полномочий, включенных в URI запроса.

422 необработанного контента (WebDAV)

423 Заблокировано (WebDAV)

Ресурс, к которому осуществляется доступ, заблокирован.

424 Неудачная зависимость (WebDAV)

Запрос не выполнен из-за сбоя предыдущего запроса.

425 Слишком рано

Указывает, что сервер не желает рисковать обработкой запроса, который может быть воспроизведен.

426 Требуется обновление

Сервер отказывается выполнять запрос с использованием текущего протокола, но может быть готов сделать это после того, как клиент перейдет на другой протокол.
Сервер отправляет заголовок Upgrade в ответе 426, чтобы указать требуемый протокол(ы).

428 Требуется предварительное условие

Исходный сервер требует, чтобы запрос был условным.
Этот ответ предназначен для предотвращения проблемы «потерянного обновления», когда клиент ПОЛУЧАЕТ состояние ресурса, изменяет его и отправляет обратно на сервер, в то время как третья сторона изменила состояние на сервере, что привело к конфликту.

429 Слишком много запросов

Сервер не желает обрабатывать запрос, поскольку поля его заголовка слишком велики.
Запрос может быть отправлен повторно после уменьшения размера полей заголовка запроса.

451 Недоступно по юридическим причинам

500 Внутренняя ошибка сервера

Сервер столкнулся с ситуацией, с которой не знает, как справиться.

501 Не реализовано

Метод запроса не поддерживается сервером и не может быть обработан. Единственные методы, которые серверы должны поддерживать (и, следовательно, не должны возвращать этот код), — это GET и HEAD.

502 Плохие врата

Этот ошибочный ответ означает, что сервер, работая как шлюз для получения ответа, необходимого для обработки запроса, получил недопустимый ответ.

503 Служба недоступна

504 Тайм-аут шлюза

Этот ответ об ошибке выдается, когда сервер действует как шлюз и не может получить ответ вовремя.

505 Версия HTTP не поддерживается

Версия HTTP, использованная в запросе, не поддерживается сервером.

506 Вариант также ведет переговоры

На сервере произошла внутренняя ошибка конфигурации: выбранный вариантный ресурс сам настроен на участие в прозрачном согласовании контента и поэтому не является подходящей конечной точкой в ​​процессе согласования.

507 Недостаточно места для хранения (WebDAV)

Метод не может быть выполнен на ресурсе, поскольку сервер не может сохранить представление, необходимое для успешного выполнения запроса.

Обнаружена петля 508 (WebDAV)

Сервер обнаружил бесконечный цикл при обработке запроса.

510 Не расширенный

Для того чтобы сервер выполнил запрос, требуются дальнейшие расширения.

511 Требуется сетевая аутентификация

Указывает, что клиенту необходимо пройти аутентификацию для получения доступа к сети.

Совместимость с браузером

Таблицы BCD загружаются только в браузере

См. также

Многие приложения позволяют создавать эффекты: аккаунты, заказы и т. д. В общем случае применяется HTTP-код состояния 200, и этого вполне достаточно. Однако код 201 более конкретен и подходит лучше:

.

HTTP-код ответа 201 Создано в успешном состоянии показывает, что запрос успешно выполнен и привёл к созданию ресурса. По сути, новый ресурс был создан до отправки этого ответа, а сам новый ресурс возвращается в телесообщение, его местоположением становится или запрос URL, или заголовок заголовка Location.

Читайте также:  Isdone dll ошибка при распаковке unarc dll вернул код ошибки 11

— Веб-документация MDN

Сбросить содержимое

Аутентификация при помощи формы может быть успешной или неудачной. При неудачном выполнении обычно повторно отображается форма с уточненными полями.

И как раз для этого предназначен код состояния 205:

HTTP-код состояния 205 Сбросить содержимое сообщает о том, что в Китае нужно бросить визуализацию документа, то есть, например, современные традиционные формы, сбрасывающие состояние холста или обновление пользовательского интерфейса.

Требуется предварительное условие

При использовании Optimistic Locking проверка при обновлении может оказаться неудачной, поскольку данные уже были обновлены кем-то ещё. По умолчанию фреймворки (например, Hibernate) в таком случае выбрасывают определения. В свою очередь, разработчики могут перехватывать его и отображать удобное информационное окно, просящее перезагрузить страницу и ввести данные повторно.

Давайте проверим код состояния 428:

Исходный сервер требует, чтобы запрос был условным. Это нужно для устранения проблемы «утерянного обновления», когда клиент при помощи GET получает состояние ресурса, изменяет его и помещает при помощи PUT обратно на сервер, в то время как третья сторона изменила состояние на сервере, что приводит к конфликту.

Этот код чётко описывает случай конфликта при optimistic locking!

В RFC 6585 упоминается термин условный и показывается пример использования заголовка If-Match. Однако в нём не показано, как конкретно достичь этого условия.

Conflict

Любопытно, что по поводу кода 409 написано следующее:

HTTP-код ответа состояния 409 Conflict говорит о конфликте запроса с текущим состоянием сервера.

Он также применим в предыдущем случае, но более обобщённый. Например, типичным примером использования будет обновление уже удалённого ресурса.

Gone

Чаще всего, когда вы пытаетесь получить при помощи GET ненайденный ресурс, сервер возвращает код 404. Но что, если ресурс существовал ранее, но теперь его нет? Интересно, что для конкретно этого случая есть альтернатива: об этом может сообщить семантика возвращаемого HTTP-кода. И именно поэтому используется 410.

HTTP-код ответа о клиентской ошибке 410 Gone показывает, что доступ к целевому ресурсу уже отсутствует на исходном сервере и это состояние, скорее всего, будет постоянным.

Если неизвестно, временное это состояние или постоянное, то нужно использовать код состояния 404.

Multiple choices

Это может показаться натянутым выбором, но спецификация IETF соответствует данному случаю.

Приложения на основе HATEOAS имеют корневую страницу, которая становится точкой входа, позволяющей выполнять дальнейшую навигацию.

Например, вот какой ответ возникает при доступе к Spring Boot Actuator:

В этом местоположении отсутствует обычный ресурс. Сервер предоставляет множество ресурсов, каждый из которых имеет свой идентификатор. Это подходит для кода состояния 300:

— IETF HTTP 1.1: Semantics and Content

Заключение

В общем случае конкретные состояния HTTP имеют смысл при наличии REST-бэкенда, доступ к которому выполняет JavaScript-фронтенд. Например, сброс формы (205) не имеет смысла, если страницу генерирует сервер.

Проблема этих кодов связана с семантикой: интерпретировать их можно по-разному. Зачем выбирать 409 вместо 428? В конечном итоге, это может быть вопросом интерпретации.

Если вы предоставляете публичный REST API, то у вас есть комбинация этих (и других) кодов, а также заголовки. Вам нужна подробная документация на все случаи, чтобы уточнить общую семантику для вашего конкретного контекста. Это не должно отталкивать вас от их использования, ведь они представляют собой богатое множество, из которого можно выбирать подходящие ответы.

Дальнейшее чтение

В этот класс выделены коды, информирующие о процессе передачи. При работе через протокол версии 1.0 сообщения с такими кодами должны игнорироваться. В версии 1.1 клиент должен быть готов принять этот класс сообщений как обычный ответ, но серверу отправлять что-либо не нужно. Сами сообщения от сервера содержат только стартовую строку ответа и, если требуется, несколько специфичных для ответа полей заголовка. Прокси-серверы подобные сообщения должны отправлять дальше от сервера к клиенту.

Сообщения данного класса информируют о случаях успешного принятия и обработки запроса клиента.
В зависимости от статуса сервер может ещё передать заголовки и тело сообщения.

Коды этого класса сообщают клиенту, что для успешного выполнения операции необходимо сделать другой запрос, как правило, по другому URI. Из данного класса пять кодов 301, 302, 303, 305 и 307 относятся непосредственно к перенаправлениям. Адрес, по которому клиенту следует произвести запрос, сервер указывает в заголовке Location. При этом допускается использование фрагментов в целевом URI.

Поведение клиентов при различных перенаправлениях описано в таблице:

Класс кодов 4xx предназначен для указания ошибок со стороны клиента. При использовании всех методов, кроме HEAD, сервер должен вернуть в теле сообщения гипертекстовое пояснение для пользователя.

Сервер вернул ошибку 403 при попытке просмотра каталога «cgi-bin», доступ к которому был запрещён

Пример ошибки 502 Bad Gateway

Коды 5xx выделены под случаи необработанных исключений при выполнении операций на стороне сервера. Для всех ситуаций, кроме использования метода HEAD, сервер должен включать в тело сообщения объяснение, которое клиент отобразит пользователю.

Основные документы по протоколу HTTP (по убыванию даты публикации)

Документы по расширениям и обновлениям протокола HTTP (по убыванию даты публикации)

Ниже представлен обзорный список всех описанных в данной статье кодов ответа:

Диаграмма принятия веб-сервером решений на основе заголовков

Статистика по кодам ответа, сгенерированная анализатором логов Webalizer

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *