HTTPQUERY
Русский

428 Precondition Required

Применение

Код состояния 428 Precondition Required сообщает, что сервер ожидает от HTTP-запросов такого типа условного характера и наличия подходящего HTTP-заголовка, например If-Match, If-None-Match, If-Modified-Since или If-Unmodified-Since.

Эти HTTP-заголовки клиенты применяют по желанию, когда сервер их поддерживает, но в данном случае сервер требует их использования. В зависимости от сценария это призвано сократить число случаев потери данных, таких как проблема «потерянного обновления».

Потерянное обновление возникает, когда клиент получает ресурс с помощью GET, изменяет его и отправляет изменённую версию обратно на сервер с помощью PUT. Без вмешательства третьей стороны проблемы нет. Если же после первоначального GET третья сторона изменила состояние ресурса на сервере, возникает конфликт. Если клиент выполняет PUT, не проверив предварительно состояние ресурса, обновление третьей стороны затирается (потерянное обновление).

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

Этот код связан с ответом 412 Precondition Failed, который сервер отправляет, когда одно или несколько условий не выполняются.

Влияние на SEO

Поисковые системы вроде Google не индексируют URL с кодом состояния ответа 428. Ранее проиндексированные URL, возвращающие этот код состояния, удаляются из результатов поиска.

Пример

Клиент ранее получил копию ресурса и с тех пор изменил локальную копию. Когда клиент пытается выполнить PUT и обновить ресурс на сервере, сервер отвечает 428 Precondition Required, поскольку HTTP-заголовки не содержали условной проверки.

Запрос

PUT /reservations.txt HTTP/1.1
Host: example.com

Ответ

HTTP/1.1 428 Precondition Required
Content-Type: text/html
Content-Length: 193

<html>
  <head>
    <title>Conditional Update Required</title>
  </head>
  <body>
   <p>This PUT request must be done conditionally.
   Try again using If-Unmodified-Since.</p>
  </body>
</html>

Как исправить

Сначала получите ресурс запросом GET и извлеките значение ETag из заголовков ответа. Затем отправьте изменяющий запрос (PUT, PATCH или DELETE) повторно с заголовком If-Match, установленным в полученное значение ETag.

Как вариант, используйте заголовок If-Unmodified-Since с датой из Last-Modified первоначального ответа на GET. Сервер сравнивает дату и продолжает обработку только в том случае, если ресурс с тех пор не изменился.

Подход с ETag точнее. Временные метки имеют точность до секунды и не улавливают быстро следующие друг за другом правки. ETag меняется при каждом изменении независимо от времени.

Убедитесь, что GET, которым вы получили ETag, обращается к тому же ресурсу, что и последующий изменяющий запрос. Использование ETag от другой записи приводит к ответу 412 Precondition Failed.

API, построенные на SAP, Salesforce и подобных платформах, обычно требуют условных запросов для операций обновления и удаления. Сверьтесь с документацией API, чтобы узнать, какие конечные точки требуют предусловий и какие заголовки-валидаторы принимаются.

На стороне сервера ответ 428 помогает предотвратить проблему «потерянного обновления», когда два клиента, редактирующие один и тот же ресурс, затирают правки друг друга. Добавление заголовков ETag ко всем изменяемым ресурсам даёт клиентам значения, необходимые для условных запросов.

Примеры кода

.NET

HttpStatusCode.PreconditionRequired

Rust

http::StatusCode::PRECONDITION_REQUIRED

Rails

:precondition_required

Go

http.StatusPreconditionRequired

Symfony

Response::HTTP_PRECONDITION_REQUIRED

Python3.5+

http.HTTPStatus.PRECONDITION_REQUIRED

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_PRECONDITION_REQUIRED

Angular

@angular/common/http/HttpStatusCode.PreconditionRequired