Чем опасен PATCH?
На собеседованиях часто спрашивают, чем отличается PUT от PATCH.
Самый простой ответ - что PATCH предназначен для частичного изменения ресурса, в то время как PUT всегда меняет ресурс полностью.
Рассмотрим пример ресурса с пользователем:
{
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"phone": "12345678"
}
Метод PATCH может позволять менять параметры ресурса по отдельности.
PATCH /users/1
{
"email": "[email protected]"
}
PUT же требует отправки всех полей ресурса, даже если меняется только одно из них.
На этом уровне кажется, что PATCH - хороший способ оптимизировать размер запросов и увеличить гибкость API.
Но если копнуть немного глубже, то появляется идемпотентность. Операция считается идемпотентной, если её повторное выполнение не изменяет результат после первого применения.
PUT должен быть всегда идемпотентным. В то время как идемпотеность PATCH зависит от реализации. Эта вариативность тоже добавляет гибкости, но несет больше рисков и требует больше внимания команды к разработке и поддержке таких методов.
Также, даже если мы сделали PATCH идемпотентным, его применение может привести к нарушению целостности данных. Допустим, мы делаем вызов с удалением email:
PATCH /users/1
{
"email": null
}
Примерно в это же время кто-то сделал другой вызов, с удалением номера телефона:
PATCH /users/1
{
"phone": null
}
Однако, по бизнес-правилам у пользователя должен быть заполнен либо email, либо телефон.
Значит, надо это заранее продумать и добавить дополнительную проверку в момент транзакции в БД. В то время как в методе PUT мы бы могли ограничиться валидацией на поля запроса.
Более того, какой-то из клиентов получит в ответе ошибку, хотя с его точки зрения он делал все правильно и конфликта быть не должно. PUT же делает для клиента очевидным результат запроса в разрезе всего ресурса и минимизирует шанс получить противоречия в значениях параметров.
Таким образом, PATCH - гибкий и мощный инструмент HTTP, но использовать его стоит с осторожностью. И точно не стоит его применять по умолчанию везде, где нужно обновление ресурса.