Редактировать конфликты и 409 против 412 ответов

У нас есть REST API, который используется для работы с бэкендом приложения. Нам нужно реализовать функцию предотвращения конфликтов, которая на запрос редактирования (POST/PUT) проверит, не изменилась ли запись между последним ее клиентом и теперь, и если бы это было, сообщило бы клиенту о конфликте.

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

Мы хотели бы использовать стандартные шаблоны REST как можно больше, поэтому мы рассмотрели следующие решения:

  • Использование If-Modified-Since. Проблема здесь в том, что она предусматривает использование метки времени, а также спецификация говорит, что вы ДОЛЖНЫ возвращать 412. Мы хотели бы вернуть более конкретный код 409, чтобы указать, что это конфликт изменений, как описанный в спецификации, вместо гораздо более общего 412, что может быть вызвано другими причинами. Это также упростит клиенту специальную обработку конфликтов редактирования, поскольку у них будет выделенный код ошибки.

  • Использование If-Match. Лучше, так как мы можем использовать любые данные, прикрепленные к нему, но снова мандаты спецификации, использующие 412, хотя 409 лучше подходят для нашего случая. Кроме того, спецификация предполагает, что If-Match связан с Etags, и мы не используем Etags для наших данных, потому что нецелесообразно вычислять правильный Etag для каждой записи. У нас есть тег, который мы будем использовать для проверок как часть данных записи, но он не отправляется, поскольку ETag и существующие клиенты не обрабатывают ETags, поэтому мы не хотели бы налагать это новое требование на клиентов, если это возможно.

  • Использование пользовательского X-заголовка. Это будет работать очень хорошо и будет довольно легко для клиентов добавить, но мы бы предпочли использовать стандартные средства REST, если это возможно.

Итак, каков рекомендуемый способ в этом случае? Есть ли способ использовать стандартные средства REST, ответить 409 и сделать все это красивым и чистым?

Ответ 1

В принципе, если у вас есть предусловия "If_ *" в заголовке, вы должны вернуть 412. Даже если вы используете пользовательский X-Header, это означает, что заголовок не имеет определения, в котором говорится, что он должен возвращать 412. Если он используется в качестве предварительных условий, если вы посмотрите на определение 412, вы должны вернуть 412 для запроса с X-заголовком.

 This response code allows the client to place preconditions on the current resource metainformation (header field data) ...

Обычно etag отправляется только в запросах как часть if- * preconditions, поэтому, если вы хотите 409, вы также не будете использовать etag.

Если вы хотите использовать 409, просто поставьте предварительные условия/постусловия в тело запроса, а не заголовок. Webdav возвращает 403/409, если условие не выполнено. 409, когда клиент может исправить запрос. см. http://www.ietf.org/rfc/rfc3253.txt.

Итак, используйте 412 для предварительных условий в заголовке, иначе 409.