Чи дозволено органу юридичної особи для запиту HTTP DELETE?


717

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


4
В ASP.NET WebApi 2 параметри FromBody ігноруються для кінцевих точок HttpDelete.
Дженні О'Рейлі

2
У мене є подібне занепокоєння, але мій випадок інший. Я хочу надіслати запит на пакетне видалення, коли я хочу видалити сто об'єктів. Безумовно, це велике підвищення продуктивності для попередніх мереж HTTP 2.0.
Singagirl

1
Чи були якісь зміни в HTTP / 2?
Jyotman Singh

Відповіді:


570

Спеціалізація прямо не забороняє і не перешкоджає цьому, тому я схильний би сказати, що це дозволено.

Microsoft бачить це так само (я чую гуркіт у аудиторії), вони стверджують у статті MSDN про метод DELETE в ADO.NET Data Services Framework :

Якщо DELETE-запит включає орган юридичної особи, це ігнорується [...]

Крім того, ось що RFC2616 (HTTP 1.1) має сказати стосовно запитів:

  • тіло об'єкта присутній тільки тоді , коли тіло повідомлення присутній (розділ 7.2)
  • наявність тіла-повідомлення сигналізується включенням Content-Lengthабо Transfer-Encodingзаголовка (розділ 4.3)
  • тіло повідомлення не повинно бути включено , коли специфікація методи запиту не дозволяє відправку тіла об'єкта (розділ 4.3)
  • тіло об'єкта явно заборонено у невеликій запитах тільки, всі інші типи запитів необмежених (розділ 9 і 9.8 конкретно)

Для відповідей це було визначено:

  • чи включено тіло повідомлення, залежить як від способу запиту, так і від статусу відповіді (розділ 4.3)
  • тіло повідомлення явно заборонено в відповідях на запити голови (розділ 9, і в Зокрема , 9.4)
  • тіло повідомлення явно заборонено в 1xx (інформаційний), 204 (без контенту), і 304 (не змінюється) відповіді (розділ 4.3)
  • всі інші відповіді включають тіло повідомлення, хоча воно може мати нульову довжину (розділ 4.3)

7
@Jason Безумовно. Ви також можете використовувати спеціальні заголовки для передачі додаткових даних, але чому б не використовувати тіло запиту.
Томалак

86
Хоча специфікація не забороняє запитам DELETE мати тіло повідомлень, розділ 4.3, схоже, вказує на те, що сервер повинен ігнорувати тіло, оскільки немає "визначеної семантики" для об'єктів DELETE : "Сервер повинен прочитати та передати тіло повідомлення на будь-який запит; якщо метод запиту не включає визначену семантику для сутності-органу, то тіло повідомлення БУДЕ ігноруватися при обробці запиту . "
Шеллі

72
Зверніть увагу, що багато клієнтів також не можуть надіслати ВИДАЛЕННЯ разом з тілом. Це просто спалило мене на Android.
Кармічний кодер

1
@KarmicCoder: Чудова справа. Детальніше: Надсилання HTTP DELETE запиту в Android .
МС Дусті

2
Багато обговорень щодо впровадження змішується зі специфікацією HTTP. Клієнти будуть реалізовувати речі так, як вони тлумачать специфікацію, не плутайте це зі значенням специфікації. Справа в тому, що специфікація залишає це неоднозначно. Я не погоджуюся з тлумаченням, що оскільки не існує визначеної семантики для суб'єкта-тіла, це означає, що його слід ігнорувати. Я думаю, що люди працюють назад від конкретних інтерпретацій клієнтів, які існують (Джерсі, тестові клієнти Android тощо) і намагаються виправдати інтерпретацію, а не намагатися бути вірними спец. Люди помиляються.
Гіброн

169

Останнє оновлення специфікації HTTP 1.1 ( RFC 7231 ) явно дозволяє органу організації в запиті DELETE:

Корисне навантаження в повідомленні DELETE-запиту не має визначеної семантики; надсилання тіла корисного навантаження на запит DELETE може призвести до відхилення запиту в деяких існуючих реалізаціях.


3
остання не затверджена версія специфікації знімає цю вимогу. Остання затверджена версія все ще цитується RFC2616.
BishopZ

4
Яка версія? Версія 20 все ще має те саме формулювання, що і версія 19, яку я пов’язував вище: "Органи запитів DELETE не мають визначеної семантики. Зауважте, що надсилання тіла на запит DELETE може викликати відхилення запиту в деяких існуючих реалізаціях."
grzes

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
Розділ 4.3.5 RFC 7231 доопрацьовує мову з версії 26 с A payload within a DELETE request message has no defined semantics. Так організм дозволений.
mndrix

6
Орган дозволений, але не повинен відповідати запиту. Використовувати це абсолютно немає сенсу.
Еверт

54

Деякі версії Tomcat та Jetty, здається, ігнорують орган сутності, якщо він присутній. Що може неприємно, якщо ви мали намір його отримати.


2
Google App Engine створює екземпляр і передає порожню суть за замовчуванням замість тіла запиту.
Олівер Хауслер

Додаткова інформація про Tomcat: Як змусити Apache Tomcat прийняти метод DELETE .
MS Dousti

50

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

Ви читали версію 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;
    }
}

15
Наявність органів у GET (і DELETE) явно посягає на HTTP та REST. Існують і інші механізми роботи з контролем одночасності (наприклад, If-Modified-Since та етаги).
Бруно

19
Як ЧИСТО поводитися з нею, коли специфікація не забороняє тілу в DELETE?
Ніл Макгуйган

5
Тому що ти не призначений нічого робити з тілом. Дивіться: stackoverflow.com/a/983458/372643
Бруно

14
Це точно та сама проблема: GET дозволяє отримати представлення ресурсу, ідентифікованого URI, а DELETE видаляє ресурс, ідентифікований URI. Використовуйте інший URI для інших версій, якщо ви хочете видалити певні версії. URI повинен бути єдиним ідентифікатором ресурсу в HTTP / REST. Використовуйте метадані в заголовках, якщо вам потрібно обробляти сумісність (наприклад, If-Unmodified-Sinceабо для Etagцього вони потрібні ).
Бруно

5
Використовуйте заголовок ETag замість поля версії в тілі
злочин

26

Мені здається, що RFC 2616 цього не визначає.

З розділу 4.3:

Присутність тіла запиту в запиті сигналізується включенням поля заголовка довжини вмісту або передачі-кодування в заголовки повідомлень запиту. Орган повідомлення НЕ МОЖЕ бути включений у запит, якщо специфікація методу запиту (розділ 5.1.1) не дозволяє надсилати суб'єкт-орган у запитах. Сервер ДОЛЖЕН прочитати та переслати тіло повідомлення на будь-який запит; якщо метод запиту не включає визначену семантику для сутності-органу, то тіло повідомлення БУДЕ ігноруватися при обробці запиту.

І розділ 9.7:

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

Успішна відповідь повинна бути 200 (ОК), якщо відповідь включає суб'єкт, що описує статус, 202 (Прийнято), якщо дія ще не здійснено, або 204 (Немає вмісту), якщо дія було прийнято, але відповідь не включає суб'єкт господарювання.

Якщо запит проходить через кеш, і Request-URI ідентифікує одну або більше поточно кешованих об'єктів, ці записи ОБОВ'ЯЗКОВО трактуються як застарілі. Відповіді на цей метод не є кешованими

Тому це прямо не дозволено чи заборонено, і є ймовірність, що проксі-сервер по ходу шляху може видалити тіло повідомлення (хоча НЕОБХІДНО його читати та пересилати).


19

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


1
for whatever reason- тому що специфікація говорить так: P
Mardoxx

20
Спеціалізація не "так говорить", вона просто говорить про те, що тіло не визначено конкретно. Якщо це не визначено, і ви хочете його проігнорувати, класно ... продовжуйте і ігноруйте його. Але відхилення запиту прямо видається крайнім і непотрібним.
Бен Фрід

1
Не покладайтеся на невизначену поведінку. Це досить поширена найкраща практика.
Еверт

@Evert є явно невизначена поведінка (як, наприклад, ви описуєте в специфікаціях мови C), і є поведінка, яка дозволена, але просто не описана. Використання тіла повідомлення в DELETE- останнє.
Альнітак

9

Варто зазначити, що специфікація OpenAPI для версії 3.0 знизила підтримку методів DELETE з тілом:

дивіться тут і тут для довідок

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


7

Здається, ElasticSearch використовує це: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api

Що означає, що Netty це підтримує.

Як згадується в коментарях, це може бути вже не так


1
Якщо ви використовуєте клієнт apache http, ви можете легко створити власні версії GET і DELETE, розширивши HttpEntityEnclosingRequestBase і зробивши метод getMethod () повернути GET або DELETE. Ми використовуємо це для розмови з еластичним пошуком.
Jilles van Gurp

2
мертве посилання - чудово. нам потрібно більше тих відповідей на посилання - ні
коттон

3
Зв'язана документація тепер містить лише POST-запити, без DELETE. Чи варто додати примітку до цієї відповіді?
дшеферд

Elasticsearch використовує тіло і для GET-запитів.
Нідхін Девід

7

Рой Філдінг у списку розсилки HTTP уточнює, що у списку розсилки http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html і каже:

Органу GET / DELETE абсолютно заборонено будь-який вплив на обробку чи тлумачення запиту

Це означає, що тіло не повинно змінювати поведінку сервера. Потім додає:

окрім необхідності читати та відкидати отримані байти, щоб підтримувати обрамлення повідомлення.

І нарешті причина не заборонити тіло:

Єдина причина, яку ми не заборонили надсилати тіло, це тому, що це призведе до ледачих реалізацій, припускаючи, що жодне тіло не буде надіслане.

Таким чином, хоча клієнти можуть надсилати тіло корисної навантаження, сервери повинні скидати його, а API не повинні визначати семантику для органу корисного навантаження на ці запити.


5

Це не визначено .

Корисне навантаження в повідомленні DELETE-запиту не має визначеної семантики; надсилання тіла корисного навантаження на запит DELETE може призвести до відхилення запиту в деяких існуючих реалізаціях.
https://tools.ietf.org/html/rfc7231#page-29



3
Ця точна цитата вже була включена в попередні відповіді, цю відповідь слід видалити.
Madbreaks

5

Використовувати DELETE з тілом ризиковано ... Я віддаю перевагу такому підходу для операцій зі списком над REST:

Регулярні операції

GET / об’єкти / Отримує всі об'єкти

GET / object / ID Отримує об’єкт із заданим ідентифікатором

POST / об’єкти Додає новий об’єкт

PUT / object / ID Додає об'єкт із заданим ідентифікатором, оновляє об'єкт

DELETE / object / ID Видаляє об'єкт із заданим ідентифікатором

Усі спеціальні дії - POST

POST / object / addList Додає список або масив об'єктів, включених до тіла

POST / objects / deleteList Видаляє список об'єктів, включених до тіла

POST / object / customQuery Створює список на основі спеціальних запитів у тілі

Якщо клієнт не підтримує ваші розширені операції, він може працювати регулярно.


Використання a POST- це не гарний спосіб RESTy для створення нових ресурсів, оскільки семантика відповідей POST неясна, особливо в контексті заголовків Location. Ви по суті залишаєте HTTP позаду та укладаєте RPC зверху. Правильний «HTTP / REST шлях» є створення ресурсів з використанням PUTж / If-None-Match: *заголовка (або spec'ing правильні методи HTTP, см і MKCOLт.д.).
hnh

4

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

Цей абзац з RFC7231 був цитований кілька разів, що підсумовує його.

Корисне навантаження в повідомленні DELETE-запиту не має визначеної семантики; надсилання тіла корисного навантаження на запит DELETE може призвести до відхилення запиту в деяких існуючих реалізаціях.

Те, що я пропустив з інших відповідей, було наслідком. Так, дозволено включати тіло за DELETEзапитами, але це семантично безглуздо. Це насправді означає, що видача DELETEзапиту органу запиту семантично рівнозначна тому, що не включати орган запиту.

Включення органу запиту не повинно впливати на запит, тому ніколи не має сенсу його включати.

tl; dr: DELETEЗапит з тілом запиту дозволений, але це ніколи не корисно.


2
"семантично безглуздий" не означає те саме, що "не має визначеної семантики". Перший означає, що він не може мати ніякого значення. Останнє просто означає, що сам RFC не визначає, якою може бути ця семантика. (Я пишу RFC)
Альнітак

1
Іншими словами, якщо реалізатор API бажає визначити для себе певну семантику, вони це абсолютно вільні.
Альнітак

1
@Alnitak це, безумовно, неправильне тлумачення. Згідно з цим визначенням, будь-який орган запиту HTTP не має визначеної семантики, але DELETE та GET спеціально викликаються в специфікації. Ось фрагмент із ще опублікованого проекту, в якому йдеться про це конкретно про запит GET:
Evert

1
Я не погоджуюся з вами, що це незрозуміло в поточно випущених RFC, але якщо ви мені не повірите, я б запропонував вам запитати авторів після їх наміру DELETE та GET. Ви побачите, що це відповідає моїй відповіді. Як і ви, я також беру участь у органах зі стандартів, і я не просто самотня людина з думкою про те, як слід трактувати RFC.
Еверт

2
Якщо це так, то 7231 є погано сформульованим, і він повинен був сказати, що "орган корисної навантаження має бути ігнорований". На який проект ви посилаєтесь вище?
Альнітак

3

Якщо хтось стикається з тестуванням цього питання, Ні, це не підтримується повсюдно.

В даний час я тестую Sahi Pro, і дуже очевидно, що http DELETE виклику позбавляє будь-яких наданих даних про тіло (великий список ідентифікаторів, які потрібно видалити масово згідно з дизайном кінцевої точки).

Я контактував з ними декілька разів, а також надсилав у три окремі пакети сценаріїв, зображень, журналів для їх перегляду, і вони досі цього не підтвердили. Невдалий виправлення та пропущені конференц-дзвінки за їх підтримкою пізніше, і я все ще не отримав надійної відповіді.

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


Він реалізований в останній версії Sahi Pro. Оскільки Sahi використовує Java для здійснення HTTP-дзвінків, а у Java з'явилася помилка до версії 1.8, яка не дозволить користувачеві зробити DELETE-запит. Тож із Java 1.8 і Sahi Pro 6.1.1 (незабаром буде оприлюднено) люди можуть надіслати DELETE запит із тілом у Sahi.
Vivek V Dwivedi

-1

Можливо, наведена нижче програма GitHUb допоможе вам отримати відповідь. Насправді сервер прикладних програм, як Tomcat, Weblogic відхиляє виклик HTTP.DELETE із завантаженням запиту. Отже, маючи на увазі всі ці речі, я додав приклад в github, будь ласка, погляньте на це

https://github.com/ashish720/spring-examples


-1

Мені вдалося виконати операцію DELETE з органом запиту. Я використовував шлюз AWS Lambda та AWS API та використовував мову Go.


3
Вони говорять про стандарти, а не про здатність. Ви навіть можете мати GET запит з тілом, що не годиться
ReZa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.