HTTP условный PUT - PullRequest
       15

HTTP условный PUT

0 голосов
/ 20 марта 2019

Чтение ответа на вопрос о идемпотентности HTTP PUT Я узнал об интересном аспекте условных запросов PUT, который приводит к следующему вопросу.

спецификация условных запросов HTTP определяется в разделе 3.1 :

Исходный сервер НЕ ДОЛЖЕН выполнять запрошенный метод, если полученное условие If-Match оценивается как ложное;вместо этого сервер происхождения ДОЛЖЕН ответить либо а) кодом состояния 412 (Не выполнено предварительное условие), либо б) одним из кодов состояния 2xx (Успешно), если сервер источника подтвердил, что запрашивается изменение состояния, а окончательное состояние ужеотражено в текущем состоянии целевого ресурса (т. е. изменение, запрошенное пользовательским агентом, уже успешно выполнено, но пользовательский агент может не знать об этом, возможно, из-за того, что предыдущий ответ был потерян или совместимое изменение было сделано каким-то другимпользовательский агент).В последнем случае сервер происхождения НЕ ДОЛЖЕН отправлять поле заголовка валидатора в ответе, если только он не может проверить, является ли запрос дубликатом непосредственно предшествующего изменения, внесенного тем же агентом пользователя.

УсловноЗапросы PUT используются, чтобы избежать проблемы потерянного обновления, когда несколько агентов работают параллельно на одном и том же ресурсе (используя оптимистическую блокировку).Предположим, что значение ресурса равно

HTTP/1.1 200 OK
Content-Type: application/json
ETag: "0"

{ "value": 0 }

Теперь два клиента одновременно хотят увеличить значение и отправить запрос PUT с телом, которое содержит новое значение, вместе с заголовком If-Match.

PUT /value HTTP/1.1
Content-Type: application/json
If-Match: "0“

{ "value": 1 }

Сервер отвечает на первый запрос со статусом 200 (OK) и на второй со статусом 412 (Precondition Failed), т.е. второй клиент должен повторитьего задача (GET, обновить ресурс и PUT его с заголовком If-Match с новым значением etag).

Теперь давайте предположим, что оба клиента не получили ответ, и поэтому оба отправляют запрос снова (очевидно, они должен использовать тот же заголовок If-Match).Согласно спецификации, сервер ДОЛЖЕН возвращать одинаковые коды состояния, то есть 200 к первому и 412 ко второму.Если сервер вернет 200 обоим, обновление будет потеряно, а если сервер вернет 412 обоим, тогда оба клиента начнут сначала, и в конце значение будет равно 3.

Мой вопрос заключается в том, как это можно реализовать на стороне сервера.Я вижу, что сервер должен хранить историю всех изменений состояния вместе с идентификацией клиента.Но как будет идентифицирован клиент?Будет ли достаточной комбинация client-ip и заголовка User-Agent?

Существуют (Java) библиотеки, которые реализуют это поведение из коробки?Мне также не ясно, какое поле заголовка валидатора нельзя отправлять клиенту.

...