Я читал много мест, где HTTP Patch неидемпотентен. Может кто-нибудь объяснить мне, почему он неидемпотентен? Потому что согласно определению - идемпотентные методы могут или не могут изменять состояние ресурса, но повторные запросы не должны иметь дополнительных побочных эффектов после первого запроса. Как повторный запрос PATCH может изменить состояние ресурса?
HTTP PATCH является идемпотентным или неидемпотентным?
Ответы (3)
В этом есть некоторая путаница. Метод PATCH не требуется, чтобы он был идемпотентным, в этом суть. Клиенты не могут предполагать, что их запросы PATCH будут идемпотентными, в отличие от PUT и GET.
Будет ли конкретная реализация идемпотентной или нет, обычно зависит от используемого алгоритма исправления, если таковой имеется. Например, плохая реализация, в которой не используется формат сравнения, который проверяет текущие значения, не будет идемпотентным.
{"op": "add", "path": "/-", "value": "foo"}
преобразует []
в ["foo"]
в первый раз, затем в ["foo", "foo"]
во второй раз, затем в ["foo", "foo", "foo"]
в третий раз и т. Д.
- person Maggyero; 11.02.2019
У меня есть сценарий, в котором PATCH не будет идемпотентным:
Предположим, два разных клиента отправляют HTTP-запросы.
Клиент X
Клиент Y
Клиент X
(1) ПАТЧ {"age": "10"}
response1-> {"age": "10", "sex": "f", "name ":" а "}
Клиент Y
(2) PATCH {"name": "b"}
response2-> {"age": "10", "sex": "f", "name ":" b "}
Клиент X
(3) PATCH {"age": "10"}
response3-> {"age": "10", "sex": "f", "name": "b"}
Вы можете видеть, что даже если запросы (1) и (3) одинаковы, ответы различаются. "name" в третьем ответе - "b".
Если это допустимый сценарий, это может быть доказательством того, что метод PATCH может отвечать разными ответами, даже если запросы одинаковы. Этого никогда не случится с методом PUT, который должен отправлять весь объект со всеми полями {возраст, пол, имя}.
Да, есть много дискуссий и путаницы в том, чем отличаются PUT и PATCH. Ясно:
СТАВИТЬ
- запрос должен содержать полное представление данного ресурса
- идемпотентен (клиент может быть уверен на 100%)
ПЛАСТЫРЬ
- запрос содержит только подмножество (только атрибуты, которые мы хотим обновить)
- не обязательно быть идемпотентным (довольно часто идемпотентным, но это не правило, поэтому клиент не может быть в этом уверен на 100%)
Из этих правил мы можем вывести некоторые правила, которые нам нужно реализовать в бэкэнде, например:
a)
- GET: пользователи / 1; тело ответа {
username: 'john', email: '[email protected]'
} - PUT: пользователи / 1; тело запроса {
username: 'john'
}
Либо ошибка проверки отправки из API (отсутствует email
), либо электронное письмо будет удалено.
Я очень надеюсь, что API вернет ошибку проверки. Итак, чтобы удалить какое-то значение, клиент должен вызвать (явно email: null
, упомянутый в запросе):
- PUT: пользователи / 1; тело запроса {
username: 'john', email: null
}
b)
- ПАТЧ: пользователи / 1; тело запроса {
username: 'john'
}
Никаких изменений на сервере. Чтобы удалить значение, клиент должен отправить:
- ПАТЧ: пользователи / 1; тело запроса {
email: null
}
Оба приведенных выше примера идемпотентны.
В другом обсуждении приведен пример того, что PATCH неидемпотентен, если патч выполняет что-то вроде добавления в коллекцию в бэкэнде: Использование методов PUT и PATCH в реальных сценариях REST API