Спокойный альтернативы, чтобы удалить тело запроса


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

4.3 Текст Сообщения

сервер должен читать и пересылать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для объекта-тела, тогда тело сообщения должно быть проигнорировано при обработке запроса.

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

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

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

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

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

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

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

4 78

4 ответа:

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

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

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

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

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

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

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

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

помните, что отдых-это не закон и не догма. Думайте об этом больше как о руководстве. Итак, когда есть смысл не следовать руководству для вашего домена, проблема, не. Просто убедитесь, что ваши потребители АПИ сообщили дисперсии.

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

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

например

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

надеюсь, что это помогает.