HTTPQUERY
Русский

409 Conflict

Применение

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

Примечание

409 Conflict означает, что запрос правильно сформирован, но конфликтует с текущим состоянием ресурса (параллельное обновление, повторное создание). 422 Unprocessable Content означает, что тело запроса синтаксически корректно, но семантически недопустимо (не пройдены правила валидации). 400 Bad Request означает, что сам запрос сформирован неверно (неразбираемое тело, недопустимые заголовки). 409 — про конфликты состояния, 422 — про валидацию, 400 — про синтаксис.

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

Влияние на SEO

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

Пример

Клиент пытается пометить существующую запись блога с «ID = 111» отметкой «like». Сервер отвечает, что запись заморожена и больше не принимает ответы или отметки.

Запрос

POST /blog/update?postid=111&flag=like HTTP/1.1
Host: example.com

Ответ

HTTP/1.1 409 Conflict
Content-Type: text/html
Content-Length: 288

<html>
  <head>
    <title>Blog Entry Frozen</title>
  </head>
  <body>
    <p>This post has been marked read-only. To post
    a reply or tag, change the status and try
    again.</p>
  </body>
</html>

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

409 Conflict означает, что запрос конфликтует с текущим состоянием ресурса на сервере.

Получите текущее состояние ресурса перед повторной попыткой. Отправьте запрос GET, чтобы получить последнюю версию. Состояние ресурса изменилось с момента, когда клиент в последний раз читал данные. Сравните возвращённый ETag или поле версии со значением, которое хранится у клиента.

Используйте условные заголовки для обнаружения конфликтов. Включайте If-Match с текущим значением ETag в запросы PUT и PATCH. Сервер отклонит запрос, если ETag больше не совпадает, что предотвратит слепую перезапись. Этот приём называется оптимистичным управлением параллелизмом.

PUT /api/resource/42 HTTP/1.1
If-Match: "abc123"
Content-Type: application/json

{"name": "updated value"}

Сервер отвечает кодом 409, когда другой клиент изменил ресурс между GET и PUT.

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

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

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

Для систем контроля версий получите последнюю версию и заново примените изменения. Получите самую свежую ревизию, согласуйте расхождения и отправьте обновление повторно. API на основе Git (GitHub, GitLab) возвращают 409, когда push конфликтует с изменениями в upstream.

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

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

Примеры кода

.NET

HttpStatusCode.Conflict

Rust

http::StatusCode::CONFLICT

Rails

:conflict

Go

http.StatusConflict

Symfony

Response::HTTP_CONFLICT

Python3.5+

http.HTTPStatus.CONFLICT

Java

java.net.HttpURLConnection.HTTP_CONFLICT

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_CONFLICT

Angular

@angular/common/http/HttpStatusCode.Conflict