Я тоже работаю над этой проблемой, и я искал в Интернете то, что кажется лучшим решением. Поскольку ни один из основных ответов, которые я могу найти, не кажется мне правильным, вот мои собственные результаты исследований.
Другие правы, что DELETE
- это путь. Вы можете включить флаг, чтобы определить, является ли это немедленно перманентом DELETE
или перемещением в корзину (и, вероятно, только администраторы могут сделать немедленный перманент DELETE
.)
DELETE /api/1/book/33
DELETE /api/1/book/33?permanent
Затем сервер может пометить книгу как удаленную. Предполагая, что у вас есть база данных SQL, это может быть что-то вроде:
UPDATE books SET status = 'deleted' WHERE book_id = 33;
Как уже упоминалось другими, как только DELETE
сделано, GET
коллекции не возвращает этот элемент. С точки зрения SQL это означает, что вы должны убедиться, что не вернули элемент со статусом deleted
.
SELECT * FROM books WHERE status <> 'deleted';
Кроме того, когда вы делаете GET /api/1/book/33
, вы должны вернуть 404 или 410. Одна из проблем с 410 состоит в том, что это означает, что ушел Навсегда (по крайней мере, это мое понимание этого кода ошибки), так Я бы возвратил 404, если элемент существует , но помечен как 'deleted'
и 410 после его окончательного удаления.
Теперь, чтобы восстановить, правильный путь - PATCH
. В отличие от PUT
, который используется для обновления элемента, ожидается, что PATCH
будет операцией с элементом. Из того, что я вижу, ожидается, что операция будет в полезной нагрузке. Чтобы это работало, ресурс должен быть доступен каким-то образом. Как предложил кто-то другой, вы можете указать область trashcan
, в которой книга появится после удаления. Примерно так будет работать для перечисления книг, которые были помещены в мусорную корзину:
GET /api/1/trashcan/books
[{"path":"/api/1/trashcan/books/33"}]
Итак, итоговый список теперь будет включать книгу № 33, которую затем вы можете PATCH
выполнить с помощью такой операции:
PATCH /api/1/trashcan/books/33
{
"operation": "undelete"
}
Если вы хотите сделать операцию более универсальной, вы можете использовать что-то вроде:
PATCH /api/1/trashcan/books/33
{
"operation": "move",
"new-path": "/api/1/books/33"
}
Тогда «перемещение» может быть использовано для других изменений URL, где это возможно в вашем интерфейсе. (Я работаю над CMS, где путь к странице находится в одной таблице с именем tree
, а каждая страница находится в другой таблице с именем page
и имеет идентификатор. Я могу изменить путь страницы, перемещая ее между пути в моей таблице tree
! Здесь очень полезен PATCH
.
К сожалению, RFC не дают четкого определения PATCH
, только то, что он должен использоваться с операцией, как показано выше, в отличие от PUT
, который принимает полезную нагрузку, представляющую новую версию, возможно частичную, целевой элемент:
PUT /api/1/books/33
{
"title": "New Title Here"
}
Принимая во внимание, что PATCH
(если бы вы поддерживали оба) было бы:
PATCH /api/1/books/33
{
"operation": "replace",
"field": "title",
"value": "New Title Here"
}
Я думаю, что поддерживать такое количество операций PATCH
было бы сумасшествием. Но я думаю, что несколько хороших примеров дают лучшее представление о том, почему PATCH
является правильным решением.
Вы можете думать об этом как: использовать патч, чтобы изменить виртуальное поле или выполнить сложную операцию, такую как перемещение, которое в противном случае потребовало бы GET
, POST
, DELETE
( и это при условии, что DELETE
является немедленным, и вы можете получить ошибки и получить частичное перемещение ...) В некотором смысле, PATCH
похоже на использование любого количества методов. Метод UNDELETE
или MOVE
будет работать аналогичным образом, но в RFC четко сказано, что существует набор стандартизированных методов , и вам непременно следует придерживаться их, а PATCH
дает вам множество комната, чтобы не пришлось добавлять свои собственные методы. Хотя в спецификациях я ничего не видел, говоря, что вы не должны добавлять свои собственные методы. Если вы это сделаете, убедитесь, что четко документировали их.