REST удалить несколько элементов в пакете - PullRequest
4 голосов
/ 04 апреля 2019

Мне нужно удалить несколько элементов по идентификатору в пакете, однако HTTP DELETE не поддерживает полезную нагрузку тела.

Варианты обхода:

1. @DELETE /path/abc?itemId=1&itemId=2&itemId=3 on the server side it will be parsed as List of ids and DELETE operation will be performed on each item.

2. @POST /path/abc including JSON payload containing all ids. { ids: [1, 2, 3] }

Насколько это плохо и какой вариантпредпочтительнее?Есть альтернативы?

Обновление : обратите внимание, что производительность является ключевым моментом, это не опция выполнения операции удаления для каждого отдельного идентификатора.

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Важно понимать, что методы HTTP работают в области «передачи документов по сети», а не в вашем собственном пользовательском домене.

Ваша модель ресурсов - это не модель вашего домена, а не ваши данныемодель.

Альтернативное написание: REST API - это фасад, который делает ваш домен похожим на веб-сайт .

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

DELETE /path/abc?itemId=1&itemId=2&itemId=3

Так что HTTPВ запросе говорится конкретно: «Применить семантику удаления к документу, описанному /path/abc?itemId=1&itemId=2&itemId=3».Тот факт, что этот документ представляет собой совокупность трех различных элементов в вашем магазине длительного пользования, каждый из которых должен быть удален независимо, является деталями реализации.Часть пункта REST заключается в том, что клиенты изолированы именно от такого рода знаний.

Однако, и я чувствую, что именно здесь теряются многие люди, метаданные, возвращаемые ответомна этот запрос на удаление клиент ничего не сообщает о ресурсах с разными идентификаторами.

Что касается клиента, /path/abc является отличным идентификатором от /path/abc?itemId=1&itemId=2&itemId=3.Так что, если клиент сделал GET из / path / abc и получил представление, которое включает в себя itemIds 1, 2, 3;и затем отправляет удаление, которое вы описываете, оно все равно будет иметь в своем собственном кэше представление, включающее /path/abc после успешного удаления.

Это может или не может быть тем, что вы хотите.Если вы выполняете REST (через HTTP), это то, о чем вы должны думать в своем дизайне.

POST /path/abc

some-useful-payload

Этот метод сообщает клиенту, что мы делаем некоторые (возможно, небезопасные) изменения в/path/abc, и в случае успеха предыдущее представление должно быть признано недействительным.Клиент должен повторить свой более ранний запрос GET /path/abc, чтобы обновить свое предыдущее представление, а не использовать ранее недействительную копию.

Но, как и раньше, это не влияет на кэшированные копии других ресурсов

/path/abc/1
/path/abc/2
/path/abc/3

Все они все еще будут храниться в кеше, даже если они были "удалены".

Если быть полностью справедливым, многим людям все равно потому что они не думают о клиентах, кэширующих данные, которые они получают с веб-сервера.И вы можете добавить метаданные к ответам, отправляемым веб-сервером, чтобы сообщить клиенту (и промежуточным компонентам), что представления не поддерживают кэширование или что результаты могут кэшироваться, но их необходимо повторять при каждом использовании.

Опять же: Ваша модель ресурсов - это не модель вашего домена, а не ваша модель данных.REST API - это другой способ осмысления происходящего, а архитектурный стиль REST настроен для решения конкретной проблемы и поэтому может не подходить для более простой задачи, которую вы пытаетесь решить.

Это не значит, что я думаю, что каждый должен проектировать свои собственные системы в соответствии с архитектурным стилем REST.REST предназначен для долгоживущих сетевых приложений, которые охватывают несколько организаций.Если вы не видите необходимости в ограничениях, не используйте их.Это нормально для меня, если вы не называете результат REST API.У меня нет проблем с системами, которые соответствуют их собственному архитектурному стилю.- Филдинг, 2008

1 голос
/ 04 апреля 2019

В течение многих лет многие люди сомневались в этом, как мы можем видеть в смежных вопросах здесь, кроме. Кажется, что принятые ответы колеблются от " наверняка, сделайте это " до ", это явно плохо обращается с протоколом ". Поскольку многие вопросы были отправлены несколько лет назад, давайте углубимся в спецификацию HTTP 1.1 с июня 2014 года ( RFC 7231 ), чтобы лучше понять, что явно не рекомендуется или нет.

Первый предложенный обходной путь:

Во-первых, о ресурсах и самом URI на Раздел 2 :

Цель HTTP-запроса называется «ресурсом». HTTP не ограничивает природу ресурса; он просто определяет интерфейс, который может использоваться для взаимодействия с ресурсами. Каждый ресурс идентифицируется унифицированным идентификатором ресурса (URI).

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

О вашем первом предложенном обходном пути (DELETE '/path/abc?itemId=1&itemId=2&itemId=3') мы можем заключить, что это что-то обескураживает, если вы думаете о ресурсе как о едином документе в вашей коллекции сущностей, и в то же время полезно подумать о ресурсе как о самой коллекции сущностей. .

Второй предложенный обходной путь:

О вашем втором предлагаемом обходном пути (POST '/path/abc' with body: { ids: [1, 2, 3] }) использование метода POST для удаления может вводить в заблуждение. Раздел Раздел 4.3.3 говорит о POST:

Метод POST запрашивает, чтобы целевой ресурс обработал представление, заключенное в запросе, в соответствии с собственной определенной семантикой ресурса. Например, POST используется для следующих функций (среди прочих): предоставление блока данных, такого как поля, введенные в форму HTML, для процесса обработки данных; Размещение сообщения на доске объявлений, в группе новостей, списке рассылки, блоге или аналогичной группе статей; Создание нового ресурса, который еще не идентифицирован исходным сервером; и добавление данных к существующему представлению (ям) ресурса.

Несмотря на то, что есть место для интерпретации функций «среди других» для POST, это явно противоречит тому факту, что у нас есть метод DELETE для удаления ресурсов, как мы видим в Раздел 4.1 :

Метод DELETE удаляет все текущие представления целевого ресурса.

Поэтому я настоятельно не рекомендую использовать POST для удаления ресурсов.

Альтернативный обходной путь:

Вдохновленный вашим вторым обходным решением, мы бы предложили еще один:

DELETE '/path/abc' with body: { ids: [1, 2, 3] }

Это почти то же самое, что было предложено во втором обходном пути, но вместо этого используется правильный метод HTTP для удаления. Здесь мы пришли к путанице относительно использования сущности body в запросе DELETE. Есть много людей, которые утверждают, что это неверно, но давайте придерживаться Раздел 4.3.5 спецификации:

Полезная нагрузка в сообщении запроса DELETE не имеет определенной семантики; отправка тела полезной нагрузки по запросу DELETE может привести к тому, что некоторые существующие реализации отклонят запрос.

Итак, мы можем сделать вывод, что спецификация не запрещает DELETE иметь полезную нагрузку body. К сожалению, некоторые существующие реализации могут отклонить запрос ... Но как это влияет на нас сегодня?

Трудно быть на 100% уверенным, но современный запрос, сделанный с fetch, просто не позволяет body для GET и HEAD. Это то, что Fetch Standard заявляет в Раздел 5.3 по пункту 34:

Если либо тело существует и имеет ненулевое значение, либо inputBody не равно нулю, а метод запроса - GET или HEAD, то выдается ошибка TypeError.

И мы можем подтвердить, что он реализован таким же образом для извлечения pollyfill в строке 342 .

Окончательные варианты:

Поскольку альтернативный обходной путь с DELETE и полезной нагрузкой body допускается в соответствии со спецификацией HTTP и поддерживается всеми современными браузерами с fetch и, поскольку IE10 с полифилом, я рекомендую этот способ выполнять пакетное удаление в действительный и полный рабочий способ.

...