Подтвердить что ты не робот

Зачем использовать двухэтапный подход к удалению нескольких элементов с помощью REST

Мы все знаем, что "стандартный" способ удаления одного элемента через REST - отправить один запрос DELETE на URI example.com/Items/666. Гранд, позвольте перейти к удалению многих сразу. Поскольку мы не требуем атомного удаления (или истинной транзакции, т.е. Всего или ничего), мы могли бы просто сказать, что клиент испытывает трудности, делает много запросов, но это не очень приятно. Таким образом, нам нужен способ, чтобы клиент мог сразу же удалить многие "Элементы".

По моему мнению, "типичным" решением этой проблемы является "двухэтапный" подход. Сначала клиент отправляет список идентификаторов элементов и возвращает URI, например example.com/Items/Collection/1. После создания этой коллекции они нажимают на DELETE.

Теперь я вижу, что это работает отлично, кроме меня, это плохое решение. Во-первых, вы вынуждаете клиента делать два запроса для размещения сервера. Во-вторых, "Я думал, что DELETE должен был удалить элемент?", Не следует ли удалять DELETE в этом URI, чтобы эффективно отменить транзакцию (это не настоящая транзакция), как бы мы ее отменили? На самом деле было бы лучше, если бы была какая-то форма "EXECUTE", но я не могу так сильно качать лодку. Это также заставляет сервер учитывать "JSON, который был POSTED, больше похож на запрос об изменении этих элементов, но запрос был DELETE... поэтому, я думаю, я удалю их". Этот подход также начинает навязывать свое состояние на клиенте/сервере, а не истинное состояние, которое я допускаю, но это своего рода.

На мой взгляд, лучшим решением было бы просто вызвать DELETE на example.com/Items (или, возможно, example.com/Items/Collection, чтобы подразумевать, что это множественное удаление) и передать данные JSON, содержащие список идентификаторов, которые вы хотите удалить. Насколько я вижу, это в основном решает все проблемы, которые был у первого метода. Он проще использовать в качестве клиента, уменьшает работу, которую должен выполнять сервер, по-настоящему без гражданства, более семантический.

Я был бы очень благодарен за это, я пропущу что-то о REST, что делает мое решение этой проблемы нереалистичным? Я также ценю ссылки на статьи, особенно если они сравнивают эти два метода; Я знаю, что это нормально не одобрено для SO. Мне нужно уметь опровергнуть, что только первый метод действительно RESTfull, докажите, что второй подход является жизнеспособным решением. Конечно, если я лаю, то неправное дерево скажу мне.

4b9b3361

Ответ 1

Я провел последнюю неделю или так читал справедливую бит в REST, и, насколько мне известно, было бы неправильно описать любое из этих решений как "RESTfull" , скорее вы должны сказать, что "ни одно решение не идет против чего REST означает".

Короткий ответ - просто, что REST, как изложено в диссертации Роя Филдинга (см. главу 5), не охватывает тему о том, как удалить ресурсы, единственного или множественного, в усадьбе REST. Правильно, нет "правильного метода RESTful для удаления ресурса"... ну, не совсем.

сам REST не определяет, как удалить ресурс, но он определяет, что любой протокол, который вы используете (помните, что REST не является протоколом) будет определять, как выполнять эти действия. Протокол обычно будет HTTP; "обычно" является ключевым словом, поскольку Fielding укажет, REST не является синонимом HTTP.

Итак, мы смотрим на HTTP, чтобы сказать, какой метод является "правильным". К сожалению, что касается HTTP, оба подхода являются жизнеспособными. Да "жизнеспособный". HTTP позволяет клиенту отправлять POST-запрос с полезной нагрузкой (для создания ресурса коллекции), а затем вызывать метод DELETE в этой новой коллекции для удаления ресурсов; он также позволит вам отправлять данные в пределах полезной нагрузки одного метода DELETE для удаления списка ресурсов. HTTP - это просто среда, с помощью которой вы отправляете запросы на сервер, и сервер должен отвечать соответствующим образом. Для меня HTTP-протокол, по-видимому, довольно открыт для интерпретации в местах, но, похоже, он устанавливает довольно четкие направления для того, что означает действия, как их следует решать и какой ответ следует давать; это просто "вы должны это делать", а не "вы должны это делать", но, возможно, я немного педантичен в формулировке.

Некоторые люди утверждают, что подход "двухэтапный" не может быть "REST", поскольку сервер должен хранить "состояние" для клиента для выполнения второго действия. Это просто непонимание какой-то части. Следует понимать, что ни клиент, ни сервер не хранят какую-либо "государственную" информацию о другом между списком POSTed и затем DELETEd. Да, список должен был быть создан до его удаления, но сервер не помнит, что это был альфа-клиент, который сделал этот список (такой подход позволит клиенту просто вызвать DELETE в качестве следующего запроса и сервер помнит для использования этого списка это вообще не было бы апатридом), как таковой, клиент должен сообщить серверу УДАЛИТЬ этот конкретный список, в список ему был дан определенный URI. Если клиент попытался УДАЛИТЬ список коллекции, который еще не существует, ему просто будет сказано, что "ресурс не может быть найден" (скорее всего, это классическая ошибка 404). Если вы хотите утверждать, что этот двухэтапный подход поддерживает состояние, вы также должны заявить, что для простого получения URI требуется состояние, поскольку URI должен сначала существовать. Утверждать, что существует это "состояние", остается недоразумением, что означает "государство". И как еще одно "доказательство" того, что такой двухступенчатый подход действительно без гражданства, вы вполне могли бы получить клиентскую альфа-версию POST, а позже бета-версию клиента (без какой-либо связи с другим клиентом), вызовите DELETE в ресурсах списка.

Я думаю, что вполне может показаться очевидным, что второй вариант просто отправки списка в полезной нагрузке запроса DELETE является апатридом. Вся информация, необходимая для заполнения запроса, сохраняется полностью в пределах одного запроса.

Можно утверждать, что действие DELETE должно быть вызвано только на "материальный" ресурс, но при этом вы явно игнорируете REpresentational часть REST; Это от имени! Репрезентативный аспект "разрешает" URI, такие как http://example.com/myService/timeNow, URI, который, когда "got" будет возвращаться, динамически, текущее время, без необходимости загрузки какого-либо файла или чтения из некоторой базы данных. Это ключевая концепция, согласно которой URI не сопоставляются непосредственно с какой-то "материальной" частью данных.

Однако есть один аспект этой безгражданности, который должен быть поставлен под сомнение. Поскольку Филдинг описывает "клиент-безстоящий-сервер" в разделе 5.1.3, он утверждает:

We next add a constraint to the client-server interaction: communication must
  be stateless in nature, as in the client-stateless-server (CSS) style of
  Section 3.4.3 (Figure 5-3), such that each request from client to server must
  contain all of the information necessary to understand the request, and
  cannot take advantage of any stored context on the server. Session state is
  therefore kept entirely on the client.

Ключевая роль здесь в моих глазах - "не может использовать любой сохраненный контекст на сервере". Теперь я дам вам, что "контекст" несколько открыт для интерпретации. Но мне трудно понять, как можно считать сохранение списка (либо в памяти, либо на диске), который будет использоваться для предоставления фактического полезного значения, не будет нарушать это правило. Из-за этого "контекста списка" операция DELETE не имеет смысла. Таким образом, я могу только заключить, что использование двухэтапного подхода для выполнения действия, такого как удаление нескольких ресурсов, не может и не должно считаться "RESTfull" .

Я также очень жалею о том, что нужно было найти аргументы для этого. По всей видимости, Интернет, по-видимому, осознал эту идею, что двухэтапный подход - это способ "RESTfull" , который делает такие действия, с аргументами "это способ RESTfull сделать это". Если вы отступите на мгновение от того, что делают все остальные, вы увидите, что любой подход требует отправки одного и того же списка, поэтому его можно игнорировать из аргумента. Оба подхода являются "репрезентативными" и "без гражданства". Единственное реальное различие заключается в том, что по какой-то причине один подход решил потребовать два запроса. Затем эти два запроса сопровождаются следующими вопросами: например, как долго вы храните эти данные для "и", как клиент сообщает серверу, что он больше не хочет эту коллекцию, но хочет сохранить фактические ресурсы, на которые он ссылается,.

Итак, я, к моменту, отвечая на свой вопрос тем же вопросом: "Почему вы даже рассматриваете двухэтапный подход?"

Ответ 2

ММО:

HTTP DELETE в существующей коллекции для удаления всех ее членов кажется прекрасным. Создание коллекции только для того, чтобы удалить все звуки участников нечетно. Как вы сами предлагаете, просто передайте идентификаторы удаляемых элементов, используя JSON (или любой другой формат полезной нагрузки). Я думаю, что сервер должен попытаться сделать несколько удалений внутренней транзакцией, хотя.

Ответ 3

Я бы сказал, что HTTP уже предоставляет метод удаления нескольких элементов в виде постоянных соединений и конвейерной обработки. На уровне протокола HTTP абсолютно нормально запрашивать методы idempotent, такие как DELETE, конвейерным способом - то есть отправлять все запросы DELETE одновременно в одном соединении и ждать всех ответов.

Это может быть проблематично для клиента AJAX, работающего в браузере, поскольку по умолчанию браузер поддерживает конвейерную поддержку. Это не ошибка HTTP, но это вина этих конкретных клиентов.