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

Альтернативы RESTful для запроса запроса DELETE

В то время как HTTP 1.1 spec, похоже, позволяет телам сообщений на DELETE, похоже, что серверы должны игнорировать его, поскольку для него нет определенной семантики.

4.3 Тело сообщения

Сервер ДОЛЖЕН читать и пересылать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для тела субъекта, тогда тело сообщения ДОЛЖНО игнорироваться при обработке запроса.

Я уже рассмотрел несколько связанных дискуссий по этой теме о SO и за ее пределами, например:

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

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

Мой вариант использования требует добавления некоторых требуемых метаданных на DELETE (например, "причина" для удаления, а также некоторые другие метаданные, необходимые для удаления). Я рассмотрел следующие варианты, ни одна из которых не кажется полностью подходящей и встроенной в спецификации HTTP и/или лучшие методы REST:

  • Тело сообщения. Спецификация указывает, что тела сообщений на DELETE не имеют семантического значения; не полностью поддерживается HTTP-клиентами; не стандартная практика.
  • Пользовательские заголовки HTTP. Требование настраиваемых заголовков обычно против стандартных методов; использование их несовместимо с остальной частью моего API, ни один из которых не требует специальных заголовков; кроме того, никакой хороший HTTP-ответ не доступен для указания неправильных значений заголовка (возможно, отдельный вопрос вообще)
  • Стандартные заголовки HTTP. Нет стандартных заголовков.
  • Параметры запроса. Добавление параметров запроса фактически изменяет удаляемый запрос-URI; против стандартных методов
  • Метод POST - (например, POST /resourceToDelete { deletemetadata }) POST не является семантической опцией для удаления; POST фактически представляет желаемое противоположное действие (то есть POST создает подчиненные ресурсы, но мне нужно удалить ресурс)
  • Несколько методов. Разделение запроса DELETE на две операции (например, метаданные PUT delete, а затем DELETE) разделяет атомную операцию на две части, что потенциально оставляет несогласованное состояние. Причина удаления (и другие связанные метаданные) не является частью самого представления ресурса.

Моим первым преимуществом было бы, вероятно, использование тела сообщения, во-вторых, для пользовательских HTTP-заголовков; однако, как указано, есть некоторые недостатки этих подходов.

Существуют ли какие-либо рекомендации или рекомендации в соответствии со стандартами REST/HTTP для включения таких необходимых метаданных в запросы DELETE? Есть ли другие альтернативы, которые я не рассматривал?

4b9b3361

Ответ 1

Несмотря на некоторые рекомендации не использовать тело сообщения для запросов DELETE, этот подход может быть уместным в некоторых случаях использования. Это тот подход, который мы использовали при оценке других вариантов, упомянутых в вопросе/ответах, и после взаимодействия с потребителями услуги.

Хотя использование тела сообщения не является идеальным, ни одна из других опций не была идеально подходящей. Тело запроса DELETE позволило нам легко и четко добавить семантику вокруг дополнительных данных/метаданных, необходимых для сопровождения операции DELETE.

Я все еще был бы открыт для других мыслей и дискуссий, но хотел бы закрыть цикл по этому вопросу. Я ценю все мысли и дискуссии по этой теме!

Ответ 2

То, что вы, кажется, хотите, - одна из двух вещей, ни одна из которых не является чистым DELETE:

  • У вас есть две операции a PUT причины удаления, за которой следует DELETE ресурса. После удаления содержимое ресурса больше не доступно никому. "Причина" не может содержать гиперссылку на удаленный ресурс. Или,
  • Вы пытаетесь изменить ресурс от state=active до state=deleted с помощью метода DELETE. Ресурсы с состоянием = deleted игнорируются вашим основным API, но могут быть доступны для чтения администратору или кому-либо, имеющему доступ к базе данных. Это разрешено - DELETE не нужно удалять данные резервного копирования для ресурса, только для удаления ресурса, открытого в этом URI.

Любая операция, требующая тела сообщения в запросе DELETE, может быть разбита на нее наиболее общей, a POST для выполнения всех необходимых задач с телом сообщения и DELETE. Я не вижу причин нарушать семантику HTTP.

Ответ 3

Учитывая сложившуюся ситуацию, я хотел бы использовать один из следующих способов:

  • Отправить PUT или PATCH. Я делаю вывод, что операция удаления является виртуальной по характеру необходимости удаления. Поэтому я считаю, что обновление записи с помощью операции PUT/PATCH является допустимым подходом, даже если это не операция DELETE как таковая.
  • Использовать параметры запроса: ресурс uri не изменяется. Я на самом деле думаю, что это также действительный подход. Вопрос, который вы связывали, говорил о том, что не разрешить удаление, если параметр запроса отсутствовал. В вашем случае у меня бы была причина по умолчанию, если причина не указана в строке запроса. Ресурс будет resource/:id. Вы можете сделать это доступным с помощью заголовков Link на ресурсе по каждой причине (с тегом rel для определения причины).
  • Используйте отдельную конечную точку для каждой причины. Используйте URL-адрес, например resource/:id/canceled. Это действительно изменяет Request-URI и определенно не RESTful. Опять же, заголовки ссылок могут сделать это доступным.

Помните, что REST - это не закон или догма. Подумайте об этом скорее как руководство. Поэтому, когда имеет смысл не следовать указаниям для вашей проблемной области, не делайте этого. Просто убедитесь, что ваши пользователи API проинформированы о дисперсии.

Ответ 4

Я предлагаю вам включить необходимые метаданные как часть самой иерархии URI. Пример (Наивный):

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

например.

DELETE /entries/range/01012012/31122012 - Удалить все записи с 01 января 2012 года по 31 декабря 2012 года.

Надеюсь, что это поможет.