HTTP-статус 412 (предварительное условие не выполнено) и управление версиями базы данных

Я реализую веб-сервис RESTful, который обращается к базе данных. Объекты в базе данных имеют версии для обнаружения нескольких обновлений. Например, если текущее значение {"name":"Bill", "comment":"tinker", "version":3}, если один пользователь ставит {"name":"Bill", "comment":"tailor", "version":3}запрос будет выполнен успешно (200 OK), и новое значение будет {"name":"Bill", "comment":"tailor", "version":4}, Если второй пользователь ставит {"name":"Bill", "comment":"sailor", "version":3"} этот запрос не будет выполнен (конфликт 409), поскольку номер версии не совпадает.

Существуют интерфейсы без RESTful, поэтому дизайн баз данных нельзя изменить. Интерфейс RESTful вызывает существующий интерфейс, который обрабатывает детали проверки версии.

Основное правило в веб-сервисах RESTful - по возможности следовать подробным данным HTTP. Было бы лучше в этом случае использовать условный заголовок в запросе и вернуть 412 Precondition Failed, если версия не совпадает? Соответствующий заголовок выглядит как If-Match. Этот заголовок принимает ETag (Entity Tag), который может быть хэшем представления текущего состояния ресурса.

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

Есть ли какая-то причина, по которой я должен это делать, кроме как "сделать его более ОТЛИЧНЫМ", что бы это ни значило?

1 ответ

Решение

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

412 следует использовать только в том случае, если предварительное условие (например, If-Match) привело к сбою сопоставления версии, тогда как 409 следует использовать, если объект вызовет конфликт (сама спецификация HTTP ссылается на это поведение в определении 409).

Следовательно, клиент, который не отправляет ETag, не будет ожидать 412. И наоборот, клиент, который отправляет ETag, не поймет, что ETag вызывают 409.

Я бы придерживался одного способа. Вы говорите, что "схема базы данных не может измениться", но это не останавливает вас (прямо на уровне HTTP-сервера), чтобы извлечь версию из представления базы данных и поместить ее в ETag, а затем на пути, возьмите заголовок If-Match и поместите его обратно в поле версии.

Но делать это полностью в теле сущности не запрещено. Вам просто нужно объяснить концепцию и то, как она работает, тогда как с помощью решения ETag вы можете просто указать людям на спецификацию HTTP.

Редактировать: И флаг версии не обязательно должен быть хешем текущего ресурса; версия вполне приемлема. ETag: "3" это совершенно правильный ETag.

Другие вопросы по тегам