В то время как спецификация HTTP 1.1, кажется, позволяет телам сообщений на запросах DELETE , похоже, это указывает на то, что серверы должны игнорировать его, поскольку для него нет определенной семантики.
4.3 Тело сообщения
Серверу СЛЕДУЕТ читать и пересылать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для тела объекта, то тело сообщения СЛЕДУЕТ игнорировать при обработке запроса.
Я уже рассмотрел несколько связанных обсуждений по этой теме в SO и за ее пределами, например:
- Разрешено ли тело объекта для HTTP-запроса DELETE?
- Полезные данные методов HTTP-запроса
- HTTP GET с телом запроса
Большинство обсуждений, похоже, сходятся во мнении, что предоставление тела сообщения при DELETE может быть разрешено. , но обычно не рекомендуется.
Кроме того, я заметил тенденцию в различных клиентских библиотеках HTTP, где все больше и больше улучшений, похоже, регистрируются для этих библиотек для поддержки тел запросов при DELETE. Большинство библиотек, кажется, подчиняются, хотя иногда и с небольшим начальным сопротивлением.
Мой вариант использования требует добавления некоторых необходимых метаданных в DELETE (например, «причина» удаления, а также некоторые другие метаданные, необходимые для удаления). Я рассмотрел следующие варианты, ни один из которых не кажется полностью подходящим и не соответствует спецификациям HTTP и / или лучшим практикам REST:
- Тело сообщения - спецификация указывает, что тела сообщения при DELETE не имеют семантического значения; не полностью поддерживается HTTP-клиентами; не стандартная практика
- Настраиваемые заголовки HTTP. Требование настраиваемых заголовков обычно противоречит стандартной практике ; их использование несовместимо с остальной частью моего API, ни один из которых не требует настраиваемых заголовков; кроме того, нет хорошего HTTP-ответа, указывающего на неправильные значения настраиваемого заголовка (вероятно, это отдельный вопрос вообще)
- Стандартные заголовки HTTP - стандартные заголовки не подходят
- Параметры запроса - добавление параметров запроса фактически изменяет удаляемый Request-URI; против стандартной практики
- Метод POST - (например
POST /resourceToDelete { deletemetadata }
) POST не является семантическим вариантом удаления; POST фактически представляет собой противоположное желаемое действие (т.е. POST создает подчиненные ресурсы; но мне нужно удалить ресурс) - Множественные методы - разделение запроса DELETE на две операции (например, PUT удалить метаданные, затем DELETE) разбивает атомарную операцию на две, потенциально оставляя несогласованное состояние. Причина удаления (и другие связанные метаданные) не являются частью самого представления ресурса.
Моим первым предпочтением, вероятно, было бы использование тела сообщения, а затем - настраиваемых заголовков HTTP; однако, как указано, у этих подходов есть некоторые недостатки.
Существуют ли какие-либо рекомендации или передовые методы, соответствующие стандартам REST / HTTP, для включения таких необходимых метаданных в запросы DELETE? Есть ли другие альтернативы, которые я не рассматривал?
источник
Jersey
, не допускают тело дляdelete
запросов.Ответы:
Несмотря на некоторые рекомендации не использовать тело сообщения для запросов DELETE, этот подход может быть уместным в определенных случаях использования. Это подход, который мы в конечном итоге использовали после оценки других вариантов, упомянутых в вопросе / ответах, и после сотрудничества с потребителями услуги.
Хотя использование тела сообщения не идеально, ни один из других вариантов не подходил идеально. Тело запроса DELETE позволило нам легко и четко добавить семантику к дополнительным данным / метаданным, которые были необходимы для сопровождения операции DELETE.
Я все еще открыт для других мыслей и обсуждений, но хотел бы замкнуть цикл по этому вопросу. Я ценю все мысли и обсуждения по этой теме!
источник
Кажется, вам нужно одно из двух, ни одна из которых не является чистой
DELETE
:PUT
по причине удаления , за которым следуетDELETE
ресурса. После удаления содержимое ресурса становится недоступным никому. «Причина» не может содержать гиперссылку на удаленный ресурс. Или,state=active
наstate=deleted
с помощьюDELETE
метода. Ресурсы с состоянием = удалено игнорируются вашим основным API, но могут быть доступны для чтения администратору или кому-то с доступом к базе данных. Это разрешено -DELETE
не нужно стирать резервные данные для ресурса, только чтобы удалить ресурс, указанный в этом URI.Любая операция, которая требует тела сообщения в
DELETE
запросе, может быть разбита на самые общие,POST
на выполнение всех необходимых задач с телом сообщения и наDELETE
. Я не вижу причин нарушать семантику HTTP.источник
PUT
разум преуспеет, аDELETE
ресурс окажется неудачным ? Как можно предотвратить противоречивое состояние?В вашей ситуации я бы выбрал один из следующих подходов:
resource/:id
. Вы можете сделать его доступным для обнаружения с помощью заголовков Link на ресурсе для каждой причины (сrel
тегом для каждой причины).resource/:id/canceled
. Это действительно меняет Request-URI и определенно не является RESTful. Опять же, заголовки ссылок могут сделать это видимым.Помните, что ОТДЫХ - это не закон или догма. Думайте об этом больше как о руководстве. Итак, если имеет смысл не следовать рекомендациям в вашей проблемной области, не делайте этого. Просто убедитесь, что ваши потребители API проинформированы об отклонении.
источник
/orders/:id
возвращает тот же ресурс, что и/orders/:id?exclude=orderdetails
. Строка запроса дает серверу только подсказки - в данном случае, чтобы исключить детали заказа в ответе (если поддерживается). Точно так же, если вы отправляете DELETE на/orders/:id
или/orders/:id?reason=canceled
или/orders/:id?reason=bad_credit
, вы по-прежнему действуете на том же базовом ресурсе. Чтобы сохранить «единый интерфейс», у меня была бы причина по умолчанию, так что отправка параметра запроса не требуется./foo?123
означает, что вы удаляете другой ресурс, чем если бы вы отправляли DELETE/foo?456
.Я предлагаю вам включить необходимые метаданные как часть самой иерархии URI. Пример (наивный):
Если вам нужно удалить записи на основе диапазона дат, вместо того, чтобы передавать дату начала и дату окончания в теле или в качестве параметров запроса, структурируйте URI таким образом, чтобы вы передавали требуемую информацию как часть URI.
например
DELETE /entries/range/01012012/31122012
- Удалить все записи в период с 1 января 2012 г. по 31 декабря 2012 г.Надеюсь это поможет.
источник
range
указанные в параметрах запроса или полезной нагрузке, которые являются основой этого вопроса: чтобы понять лучший подход к проблеме, который, я бы сказал, не в этом.