Разрешено ли тело объекта для запроса HTTP DELETE?
718
При выдаче запроса HTTP DELETE URI запроса должен полностью идентифицировать ресурс для удаления. Однако допустимо ли добавлять дополнительные метаданные как часть сущности запроса?
В ASP.NET WebApi 2 параметры FromBody игнорируются для конечных точек HttpDelete.
Дженни О'Рейли
2
У меня похожая проблема, но у меня другой случай. Я хочу создать пакетный запрос на удаление, когда я хочу удалить сто объектов. Конечно, это большое повышение производительности для сетей до HTTP 2.0.
Singagirl
1
Были ли какие-либо изменения в HTTP / 2?
Джотман Сингх
Ответы:
570
Спецификация явно не запрещает и не препятствует этому, поэтому я бы сказал, что это разрешено.
@ Джейсон Определенно. Вы также можете использовать пользовательские заголовки для передачи дополнительных данных, но почему бы не использовать тело запроса.
Томалак
86
Хотя спецификация не запрещает запросам DELETE иметь тело сообщения, раздел 4.3, по- видимому, указывает, что тело должно игнорироваться телом, так как не существует «определенной семантики» для тел объекта DELETE : «Сервер ДОЛЖЕН прочитать и переслать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для тела объекта, то тело сообщения ДОЛЖНО игнорироваться при обработке запроса . "
Шелли
72
Обратите внимание, что многие клиенты также не могут отправить DELETE с телом. Это просто сжег меня на Android.
Много обсуждений о реализации, смешанной с HTTP-спецификацией. Клиенты будут реализовывать вещи так, как они интерпретируют спецификацию, не путайте это со смыслом спецификации. Дело в том, что спецификация оставляет это неоднозначным. Я не согласен с интерпретацией, что, поскольку не существует определенной семантики для тела-сущности, есть смысл, что ее следует игнорировать. Я думаю, что люди работают в обратном направлении от существующих конкретных интерпретаций клиентов (Джерси, тестовые клиенты Android и т. Д.) И пытаются оправдать интерпретацию, а не пытаться быть верными спецификации. Люди подвержены ошибкам.
Gibron
169
Последнее обновление спецификации HTTP 1.1 ( RFC 7231 ) явно разрешает тело объекта в запросе DELETE:
Полезная нагрузка в сообщении запроса DELETE не имеет определенной семантики; отправка тела полезной нагрузки по запросу DELETE может привести к тому, что некоторые существующие реализации отклонят запрос.
последняя не утвержденная версия спецификации устраняет это требование. Последней утвержденной версией по-прежнему является RFC2616, указанный выше.
BishopZ
4
Какая версия? Версия 20 по-прежнему имеет ту же формулировку, что и версия 19, на которую я ссылался выше: «Тела в запросах DELETE не имеют определенной семантики. Обратите внимание, что отправка тела в запросе DELETE может привести к тому, что некоторые существующие реализации отклонят запрос».
выпадает
11
Версия 26 предполагает, что вы можете разрешить тело: A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.Итак, оно поставляется с предупреждением об обратной совместимости, оно предполагает, что в следующем стандарте будет сказано: «Да! DELETEможет иметь тело.
Pure.Krome
4
RFC 7231 раздел 4.3.5 завершает язык с версии 26 с A payload within a DELETE request message has no defined semantics. Так что тело разрешено.
mndrix
6
Тело разрешено, но не должно относиться к запросу. Там нет абсолютно никакого смысла в его использовании.
Эверт
55
Некоторые версии Tomcat и Jetty, похоже, игнорируют тело объекта, если оно присутствует. Что может быть неприятно, если вы намеревались получить его.
Вы должны получить оптимистическое исключение блокировки. Перечитайте запись, увидите, что это важно, и, возможно, не удалите ее.
Другая причина его использования - удаление нескольких записей за один раз (например, сетка с флажками выбора строк).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Обратите внимание, что каждое сообщение имеет свою версию. Возможно, вы можете указать несколько версий, используя несколько заголовков, но Джордж, это проще и намного удобнее.
Это работает в Tomcat (7.0.52) и Spring MVC (4.05), возможно, с более ранними версиями:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
Наличие тел в GET (и DELETE) явно плохо обращается с HTTP и REST. Существуют и другие механизмы управления параллелизмом (например, If-Modified-Since и etags).
Бруно
19
Как это ЯВНО плохо с ним обращаться, когда спецификация не запрещает тело в DELETE?
Это точно такая же проблема: GET позволяет вам получить представление ресурса, идентифицированного URI, а DELETE удаляет ресурс, идентифицированный URI. Используйте другой URI для других версий, если вы хотите удалить определенные версии. URI должен быть единственным идентификатором ресурса в HTTP / REST. Используйте метаданные в заголовках, если вам нужно обрабатывать параллелизм (например, If-Unmodified-Sinceили для Etagэтого они нужны ).
Бруно
5
Используйте заголовок ETag вместо поля версии в теле
Присутствие тела сообщения в запросе сигнализируется включением поля заголовка Content-Length или Transfer-Encoding в заголовки сообщения запроса. Тело сообщения НЕ ДОЛЖНО быть включено в запрос, если спецификация метода запроса (раздел 5.1.1) не позволяет отправлять тело объекта в запросах. Сервер ДОЛЖЕН прочитать и переслать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для тела объекта, то тело сообщения ДОЛЖНО игнорироваться при обработке запроса.
И раздел 9.7:
Метод DELETE запрашивает, чтобы исходный сервер удалил ресурс, указанный в Request-URI. Этот метод МОЖЕТ быть отменен вмешательством человека (или другими средствами) на исходном сервере. Клиент не может быть гарантирован, что операция была выполнена, даже если код состояния, возвращенный с исходного сервера, указывает, что действие было успешно выполнено. Однако серверу НЕ СЛЕДУЕТ указывать успех, если только во время ответа он не намерен удалить ресурс или переместить его в недоступное место.
Успешный ответ ДОЛЖЕН быть 200 (ОК), если ответ включает в себя объект, описывающий статус, 202 (Принят), если действие еще не было выполнено, или 204 (Нет содержимого), если действие было выполнено, но ответ не включает сущность.
Если запрос проходит через кеш, а Request-URI идентифицирует один или несколько кешируемых в данный момент объектов, эти записи ДОЛЖНЫ рассматриваться как устаревшие. Ответы на этот метод не кешируются.
Так что это явно не разрешено или не разрешено, и есть вероятность, что прокси-сервер по пути может удалить тело сообщения (хотя он ДОЛЖЕН прочитать и переслать его).
Просто наперед, если вы предоставите тело в своем запросе DELETE и используете балансировщик нагрузки HTTPS в облаке Google, он отклонит ваш запрос с ошибкой 400. Я ударился головой о стену и обнаружил, что Google по какой-то причине считает запрос DELETE с телом некорректным запросом.
for whatever reason- потому что спецификация так говорит: P
Mardoxx
20
Спецификация не «говорит так», она просто говорит, что тело не определено конкретно. Если это не определено, и вы хотите игнорировать это, круто ... продолжайте и игнорируйте это. Но прямое отклонение запроса кажется крайним и ненужным.
Бен Фрид
1
Не полагайтесь на неопределенное поведение. Это довольно распространенная лучшая практика.
Эверт
@ Обратимся к явному неопределенному поведению (например, описанному в спецификациях языка Си), и такое поведение разрешено, но просто не описано. Использование тела сообщения DELETEявляется последним.
Альнитак
9
Стоит отметить, что в спецификации OpenAPI для версии 3.0 отсутствует поддержка методов DELETE с телом:
Если вы используете Apache http-клиент, вы можете легко создавать свои собственные версии GET и DELETE, расширяя HttpEntityEnclosingRequestBase и заставляя метод getMethod () возвращать GET или DELETE. Мы используем это для общения с эластичным поиском.
Жиль ван Гурп
2
мертвая ссылка - отлично. нам нужно больше ответов на эти ссылки - нет
Котттон
3
Связанная документация теперь содержит только запросы POST, но не DELETE. Может быть стоит добавить примечание к этому ответу?
dshepherd
Elasticsearch также использует body с запросами GET.
Тело GET / DELETE категорически запрещено оказывать какое-либо влияние на обработку или интерпретацию запроса.
Это означает, что тело не должно изменять поведение сервера. Затем он добавляет:
кроме необходимости читать и отбрасывать полученные байты, чтобы поддерживать кадрирование сообщения.
И, наконец, причина не запрещающего тела:
Единственная причина, по которой мы не запрещали отправку тела, заключается в том, что это приведет к отложенным реализациям, предполагающим, что тело не будет отправлено.
Поэтому, хотя клиенты могут отправлять тело полезной нагрузки, серверы должны его отбрасывать, а API не должны определять семантику для тела полезной нагрузки в этих запросах.
Полезная нагрузка в сообщении запроса DELETE не имеет определенной семантики; отправка тела полезной нагрузки по запросу DELETE может привести к тому, что некоторые существующие реализации отклонят запрос. https://tools.ietf.org/html/rfc7231#page-29
Использование a POSTне является хорошим способом REST для создания новых ресурсов, потому что семантика ответов POST неясна, особенно в контексте заголовков Location. По сути, вы оставляете HTTP позади и ставите RPC сверху. Правильный «HTTP / REST путь» является создание ресурсов с использованием PUTж / If-None-Match: *заголовка (или spec'ing правильные методы HTTP, см и MKCOLт.д.).
HNH
4
Я не думаю, что хороший ответ на это был опубликован, хотя было много хороших комментариев к существующим ответам. Я подниму суть этих комментариев в новый ответ:
Полезная нагрузка в сообщении запроса DELETE не имеет определенной семантики; отправка тела полезной нагрузки по запросу DELETE может привести к тому, что некоторые существующие реализации отклонят запрос.
То, что я пропустил из других ответов, было значение. Да, разрешено включать тело в DELETEзапросах, но это семантически бессмысленно. На самом деле это означает, что отправка DELETEзапроса с телом запроса семантически эквивалентна отсутствию тела запроса.
Включение тела запроса не должно влиять на запрос, поэтому нет смысла включать его.
tl; dr: Технически DELETEзапрос с телом запроса разрешен, но делать это бесполезно.
«семантически бессмысленный» не означает то же самое, что «не имеет определенной семантики». Первое означает, что оно не может иметь никакого значения. Последнее просто означает, что сам RFC не указывает, какой может быть эта семантика. (Я пишу RFC)
Альнитак
1
Другими словами, если разработчик API желает определить некоторую семантику для себя, он совершенно свободен в этом.
Альнитак
1
@Alnitak это определенно неверное толкование. По этому определению любое тело HTTP-запроса не имеет определенной семантики, но DELETE и GET специально вызываются в спецификации. Вот фрагмент из еще
Evert
1
Я не согласен с вами, что это неясно в выпущенных в настоящий момент документах RFC, но если вы мне не верите, я бы пригласил вас спросить авторов об их намерениях по DELETE и GET. Вы обнаружите, что это соответствует моему ответу. Как и вы, я также участвую в работе органов по стандартизации, и я не просто одинокий человек с мнением о том, как следует интерпретировать RFC.
Эверт
2
Если это так, то 7231 плохо сформулирован и должен был сказать «тело полезной нагрузки ДОЛЖНО игнорироваться». На какой проект вы ссылаетесь выше?
Альнитак
3
В случае, если кто-то сталкивается с этой проблемой тестирования, Нет, это не универсально поддерживается.
В настоящее время я тестирую с Sahi Pro, и очень очевидно, что вызов http DELETE удаляет все предоставленные данные тела (большой список идентификаторов, которые нужно удалить в массе в соответствии с дизайном конечной точки).
Я связывался с ними несколько раз, а также отправил три отдельных пакета с записками, изображениями и журналами, чтобы они могли их просмотреть, и они до сих пор не подтвердили это. Неудачный патч и пропущенные конференц-звонки с их поддержкой позже, и я до сих пор не получил точного ответа.
Я уверен, что Sahi не поддерживает это, и я думаю, что многие другие инструменты следуют за набором.
Он реализован в последней версии Sahi Pro. Поскольку Sahi использует Java для выполнения HTTP-вызовов, а в Java была ошибка до версии 1.8, которая не позволяла пользователю сделать запрос DELETE. Таким образом, с Java 1.8 и Sahi Pro 6.1.1 (скоро будет доступно), люди могут сделать запрос DELETE с телом в Sahi.
Vivek V Dwivedi
-1
Может быть, приведенный ниже URL-адрес GitHUb поможет вам получить ответ. На самом деле, сервер приложений, такой как Tomcat, Weblogic отклоняет вызов HTTP.DELETE с полезной нагрузкой запроса. Имея в виду все это, я добавил пример в github, пожалуйста, посмотрите на это
Ответы:
Спецификация явно не запрещает и не препятствует этому, поэтому я бы сказал, что это разрешено.
Microsoft видит то же самое (я слышу ропот в аудитории), в статье MSDN говорится о методе DELETE в ADO.NET Data Services Framework :
Кроме того, вот что говорит RFC2616 (HTTP 1.1) в отношении запросов:
Content-Length
илиTransfer-Encoding
(раздел 4.3)Для ответов это было определено:
источник
Последнее обновление спецификации HTTP 1.1 ( RFC 7231 ) явно разрешает тело объекта в запросе DELETE:
источник
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
Итак, оно поставляется с предупреждением об обратной совместимости, оно предполагает, что в следующем стандарте будет сказано: «Да!DELETE
может иметь тело.A payload within a DELETE request message has no defined semantics
. Так что тело разрешено.Некоторые версии Tomcat и Jetty, похоже, игнорируют тело объекта, если оно присутствует. Что может быть неприятно, если вы намеревались получить его.
источник
Одной из причин использования тела в запросе на удаление является оптимистичное управление параллелизмом.
Вы читаете версию 1 записи.
Ваш коллега читает версию 1 записи.
Ваш коллега меняет запись и обновляет базу данных, которая обновляет версию до 2:
Вы пытаетесь удалить запись:
Вы должны получить оптимистическое исключение блокировки. Перечитайте запись, увидите, что это важно, и, возможно, не удалите ее.
Другая причина его использования - удаление нескольких записей за один раз (например, сетка с флажками выбора строк).
Обратите внимание, что каждое сообщение имеет свою версию. Возможно, вы можете указать несколько версий, используя несколько заголовков, но Джордж, это проще и намного удобнее.
Это работает в Tomcat (7.0.52) и Spring MVC (4.05), возможно, с более ранними версиями:
источник
If-Unmodified-Since
или дляEtag
этого они нужны ).Мне кажется, что RFC 2616 не определяет это.
Из раздела 4.3:
И раздел 9.7:
Так что это явно не разрешено или не разрешено, и есть вероятность, что прокси-сервер по пути может удалить тело сообщения (хотя он ДОЛЖЕН прочитать и переслать его).
источник
Просто наперед, если вы предоставите тело в своем запросе DELETE и используете балансировщик нагрузки HTTPS в облаке Google, он отклонит ваш запрос с ошибкой 400. Я ударился головой о стену и обнаружил, что Google по какой-то причине считает запрос DELETE с телом некорректным запросом.
источник
for whatever reason
- потому что спецификация так говорит: PDELETE
является последним.Стоит отметить, что в спецификации OpenAPI для версии 3.0 отсутствует поддержка методов DELETE с телом:
смотрите здесь и здесь для ссылок
Это может повлиять на вашу реализацию, документацию или использование этих API в будущем.
источник
Кажется, ElasticSearch использует это: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Что означает, что Netty поддерживает это.
Как упомянуто в комментариях, это может быть не так больше
источник
Рой Филдинг в списке рассылки HTTP уточняет, что в списке рассылки http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html и говорит:
Это означает, что тело не должно изменять поведение сервера. Затем он добавляет:
И, наконец, причина не запрещающего тела:
Поэтому, хотя клиенты могут отправлять тело полезной нагрузки, серверы должны его отбрасывать, а API не должны определять семантику для тела полезной нагрузки в этих запросах.
источник
Это не определено .
источник
Использование DELETE с Body является рискованным ... Я предпочитаю такой подход для операций со списками, а не для REST:
Регулярные операции
GET / objects / Получает все объекты
GET / object / ID Получает объект с указанным идентификатором
POST / objects Добавляет новый объект
PUT / object / ID Добавляет объект с указанным идентификатором, обновляет объект
DELETE / object / ID Удаляет объект с указанным идентификатором
Все пользовательские действия POST
POST / objects / addList Добавляет список или массив объектов, включенных в тело
POST / objects / deleteList Удаляет список объектов, включенных в тело
POST / objects / customQuery Создает список на основе пользовательского запроса в теле.
Если клиент не поддерживает ваши расширенные операции, он может работать в обычном режиме.
источник
POST
не является хорошим способом REST для создания новых ресурсов, потому что семантика ответов POST неясна, особенно в контексте заголовков Location. По сути, вы оставляете HTTP позади и ставите RPC сверху. Правильный «HTTP / REST путь» является создание ресурсов с использованиемPUT
ж /If-None-Match: *
заголовка (или spec'ing правильные методы HTTP, см иMKCOL
т.д.).Я не думаю, что хороший ответ на это был опубликован, хотя было много хороших комментариев к существующим ответам. Я подниму суть этих комментариев в новый ответ:
Этот абзац из RFC7231 цитировался несколько раз, что подводит итог.
То, что я пропустил из других ответов, было значение. Да, разрешено включать тело в
DELETE
запросах, но это семантически бессмысленно. На самом деле это означает, что отправкаDELETE
запроса с телом запроса семантически эквивалентна отсутствию тела запроса.Включение тела запроса не должно влиять на запрос, поэтому нет смысла включать его.
tl; dr: Технически
DELETE
запрос с телом запроса разрешен, но делать это бесполезно.источник
В случае, если кто-то сталкивается с этой проблемой тестирования, Нет, это не универсально поддерживается.
В настоящее время я тестирую с Sahi Pro, и очень очевидно, что вызов http DELETE удаляет все предоставленные данные тела (большой список идентификаторов, которые нужно удалить в массе в соответствии с дизайном конечной точки).
Я связывался с ними несколько раз, а также отправил три отдельных пакета с записками, изображениями и журналами, чтобы они могли их просмотреть, и они до сих пор не подтвердили это. Неудачный патч и пропущенные конференц-звонки с их поддержкой позже, и я до сих пор не получил точного ответа.
Я уверен, что Sahi не поддерживает это, и я думаю, что многие другие инструменты следуют за набором.
источник
Может быть, приведенный ниже URL-адрес GitHUb поможет вам получить ответ. На самом деле, сервер приложений, такой как Tomcat, Weblogic отклоняет вызов HTTP.DELETE с полезной нагрузкой запроса. Имея в виду все это, я добавил пример в github, пожалуйста, посмотрите на это
https://github.com/ashish720/spring-examples
источник
Мне удалось реализовать операцию УДАЛИТЬ с телом запроса. Я использовал AWS Lambda и AWS API gateway и использовал язык Go.
источник