Разрешено ли тело объекта для запроса HTTP DELETE? - PullRequest
597 голосов
/ 18 ноября 2008

При отправке запроса HTTP DELETE URI запроса должен полностью идентифицировать ресурс для удаления. Однако допустимо ли добавлять дополнительные метаданные как часть сущности запроса?

Ответы [ 14 ]

490 голосов
/ 18 ноября 2008

Спецификация не запрещает и не запрещает ее, поэтому я бы сказал, что она разрешена.

Microsoft видит это так же (я слышу ропот в аудитории), в статье MSDN говорится о УДАЛЕННОМ методе ADO.NET Data Services Framework :

Если запрос DELETE включает тело объекта, тело игнорируется [...]

Кроме того, вот что RFC2616 (HTTP 1.1) должен сказать в отношении запросов:

  • тело объекта присутствует, только если присутствует тело сообщения (раздел 7.2)
  • наличие тела сообщения сигнализируется включением заголовка Content-Length или Transfer-Encoding (раздел 4.3)
  • a body-message не должно быть включено, если спецификация метода запроса не позволяет отправить entity-body (раздел 4.3)
  • и сущность явно запрещены только в запросах TRACE, все остальные типы запросов не ограничены (в частности, разделы 9 и 9.8)

Для ответов это было определено:

  • Включено ли тело сообщения , зависит как от метода запроса , так и от статуса ответа (раздел 4.3)
  • a тело сообщения явно запрещено в ответах на запросы HEAD (в частности, разделы 9 и 9.4)
  • a тело сообщения явно запрещено в ответах 1xx (информационное), 204 (без содержимого) и 304 (не изменено) (раздел 4.3)
  • все остальные ответы включают тело сообщения, хотя оно может иметь нулевую длину (раздел 4.3)
144 голосов
/ 04 апреля 2012

Последнее обновление спецификации HTTP 1.1 ( RFC 7231 ) явно разрешает тело объекта в запросе DELETE:

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

52 голосов
/ 15 января 2010

Некоторые версии Tomcat и Jetty, похоже, игнорируют тело объекта, если оно присутствует. Что может быть неприятно, если вы намеревались его получить.

44 голосов
/ 09 августа 2013

Одной из причин использования тела в запросе на удаление является оптимистический контроль параллелизма.

Вы читаете версию 1 записи.

GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }

Ваш коллега читает версию 1 записи.

GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }

Ваш коллега меняет запись и обновляет базу данных, которая обновляет версию до 2:

PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }

Вы пытаетесь удалить запись:

DELETE /some-resource/1 { id:1, version:1 }
409 Conflict

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

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

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;
    }
}
27 голосов
/ 18 ноября 2008

Мне кажется, что RFC 2616 не определяет это.

Из раздела 4.3:

Наличие тела сообщения в запросе сигнализируется включение поля заголовка Content-Length или Transfer-Encoding в заголовки сообщения запроса. Тело сообщения НЕ ДОЛЖНО быть включено в запрос, если спецификация метода запроса (раздел 5.1.1) не позволяет отправлять объект-тело в запросах. Сервер ДОЛЖЕН читать и пересылать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для тела объекта, то тело сообщения ДОЛЖНО игнорироваться при обработке запроса.

А, раздел 9.7:

Метод DELETE запрашивает, чтобы исходный сервер удалил ресурс идентифицируется запросом-URI. Этот метод МОЖЕТ быть отменен человеком вмешательство (или другие средства) на исходном сервере. Клиент не может гарантировать, что операция была выполнена, даже если Код состояния, возвращаемый сервером происхождения, указывает на то, что действие был успешно завершен. Тем не менее, сервер не должен указывают на успех, если во время ответа намерен удалить ресурс или переместить его в недоступный место.

Успешный ответ ДОЛЖЕН быть 200 (ОК), если ответ включает объект, описывающий статус, 202 (Принят), если действие не имеет еще не вступил в силу, или 204 (без содержимого), если действие было принято но ответ не включает сущность.

Если запрос проходит через кеш, а Request-URI идентифицирует одна или несколько кешированных в данный момент сущностей, эти записи ДОЛЖНЫ быть рассматривается как несвежий. Ответы на этот метод не кэшируются. C

Так что это явно не разрешено или не разрешено, и есть вероятность, что прокси по пути может удалить тело сообщения (хотя оно ДОЛЖНО прочитать и переслать его).

15 голосов
/ 26 мая 2016

Просто наперед, если вы предоставите тело в своем запросе DELETE и используете балансировщик нагрузки HTTPS в облаке Google, он отклонит ваш запрос с ошибкой 400. Я ударился головой о стену и обнаружил, что Google по какой-то причине считает запрос DELETE с телом некорректным запросом.

7 голосов
/ 27 мая 2013

Кажется, ElasticSearch использует это: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api

Что означает, что Netty поддерживает это.

Как упомянуто в комментариях, это может быть не так

6 голосов
/ 09 января 2017

Это не определено .

Полезная нагрузка в сообщении запроса DELETE не имеет определенной семантики; отправка тела полезной нагрузки по запросу DELETE может вызвать некоторые существующие реализации, чтобы отклонить запрос.
https://tools.ietf.org/html/rfc7231#page-29

5 голосов
/ 09 ноября 2018

Стоит отметить, что в спецификации OpenAPI для версии 3.0 прекращена поддержка методов DELETE с телом:

см. здесь и здесь для ссылок

Это может повлиять на вашу реализацию, документацию или использование этих API в будущем.

3 голосов
/ 17 февраля 2019

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

Этот абзац из RFC7231 цитировался несколько раз, что суммирует его.

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

То, что я упустил из других ответов, было следствием. Да, разрешено включать тело в DELETE запросах, но это семантически бессмысленно. Это на самом деле означает, что выдача DELETE запроса с телом запроса семантически эквивалентна отсутствию тела запроса.

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

tl; dr: Технически DELETE запрос с телом запроса разрешен, но это бесполезно.

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