Під час видачі HTTP DELETE запиту URI запиту повинен повністю ідентифікувати ресурс для видалення. Однак чи можна додавати додаткові метадані як частина органу запиту?
Під час видачі HTTP DELETE запиту URI запиту повинен повністю ідентифікувати ресурс для видалення. Однак чи можна додавати додаткові метадані як частина органу запиту?
Відповіді:
Спеціалізація прямо не забороняє і не перешкоджає цьому, тому я схильний би сказати, що це дозволено.
Microsoft бачить це так само (я чую гуркіт у аудиторії), вони стверджують у статті MSDN про метод DELETE в ADO.NET Data Services Framework :
Якщо DELETE-запит включає орган юридичної особи, це ігнорується [...]
Крім того, ось що RFC2616 (HTTP 1.1) має сказати стосовно запитів:
Content-Length
або Transfer-Encoding
заголовка (розділ 4.3)Для відповідей це було визначено:
Останнє оновлення специфікації HTTP 1.1 ( RFC 7231 ) явно дозволяє органу організації в запиті DELETE:
Корисне навантаження в повідомленні DELETE-запиту не має визначеної семантики; надсилання тіла корисного навантаження на запит 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 запису.
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;
}
}
If-Unmodified-Since
або для Etag
цього вони потрібні ).
Мені здається, що RFC 2616 цього не визначає.
З розділу 4.3:
Присутність тіла запиту в запиті сигналізується включенням поля заголовка довжини вмісту або передачі-кодування в заголовки повідомлень запиту. Орган повідомлення НЕ МОЖЕ бути включений у запит, якщо специфікація методу запиту (розділ 5.1.1) не дозволяє надсилати суб'єкт-орган у запитах. Сервер ДОЛЖЕН прочитати та переслати тіло повідомлення на будь-який запит; якщо метод запиту не включає визначену семантику для сутності-органу, то тіло повідомлення БУДЕ ігноруватися при обробці запиту.
І розділ 9.7:
Метод DELETE вимагає, щоб сервер-джерело видалив ресурс, ідентифікований URI-запитом. Цей метод МОЖЕ бути відмінений втручанням людини (або іншими способами) на початковий сервер. Клієнту не можна гарантувати, що операція була здійснена, навіть якщо код статусу, повернутий з початкового сервера, вказує на те, що дія успішно завершена. Однак сервер НЕ повинен вказувати на успіх, якщо під час надання відповіді він не має наміру видалити ресурс або перемістити його в недоступне місце.
Успішна відповідь повинна бути 200 (ОК), якщо відповідь включає суб'єкт, що описує статус, 202 (Прийнято), якщо дія ще не здійснено, або 204 (Немає вмісту), якщо дія було прийнято, але відповідь не включає суб'єкт господарювання.
Якщо запит проходить через кеш, і Request-URI ідентифікує одну або більше поточно кешованих об'єктів, ці записи ОБОВ'ЯЗКОВО трактуються як застарілі. Відповіді на цей метод не є кешованими
Тому це прямо не дозволено чи заборонено, і є ймовірність, що проксі-сервер по ходу шляху може видалити тіло повідомлення (хоча НЕОБХІДНО його читати та пересилати).
Якщо ви подаєте тіло у своєму запиті DELETE та використовуєте хмаровий балансир завантаження HTTPS у хмарі Google, він відхилить ваш запит із помилкою 400. Я стукнув головою об стіну і з’ясував, що Google з будь-якої причини вважає, що DELETE-запит з тілом є неправильним запитом.
for whatever reason
- тому що специфікація говорить так: P
DELETE
- останнє.
Здається, 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 і каже:
Органу GET / DELETE абсолютно заборонено будь-який вплив на обробку чи тлумачення запиту
Це означає, що тіло не повинно змінювати поведінку сервера. Потім додає:
окрім необхідності читати та відкидати отримані байти, щоб підтримувати обрамлення повідомлення.
І нарешті причина не заборонити тіло:
Єдина причина, яку ми не заборонили надсилати тіло, це тому, що це призведе до ледачих реалізацій, припускаючи, що жодне тіло не буде надіслане.
Таким чином, хоча клієнти можуть надсилати тіло корисної навантаження, сервери повинні скидати його, а API не повинні визначати семантику для органу корисного навантаження на ці запити.
Це не визначено .
Корисне навантаження в повідомленні DELETE-запиту не має визначеної семантики; надсилання тіла корисного навантаження на запит DELETE може призвести до відхилення запиту в деяких існуючих реалізаціях.
https://tools.ietf.org/html/rfc7231#page-29
Використовувати DELETE з тілом ризиковано ... Я віддаю перевагу такому підходу для операцій зі списком над REST:
Регулярні операції
GET / об’єкти / Отримує всі об'єкти
GET / object / ID Отримує об’єкт із заданим ідентифікатором
POST / об’єкти Додає новий об’єкт
PUT / object / ID Додає об'єкт із заданим ідентифікатором, оновляє об'єкт
DELETE / object / ID Видаляє об'єкт із заданим ідентифікатором
Усі спеціальні дії - POST
POST / object / addList Додає список або масив об'єктів, включених до тіла
POST / objects / deleteList Видаляє список об'єктів, включених до тіла
POST / object / customQuery Створює список на основі спеціальних запитів у тілі
Якщо клієнт не підтримує ваші розширені операції, він може працювати регулярно.
POST
- це не гарний спосіб RESTy для створення нових ресурсів, оскільки семантика відповідей POST неясна, особливо в контексті заголовків Location. Ви по суті залишаєте HTTP позаду та укладаєте RPC зверху. Правильний «HTTP / REST шлях» є створення ресурсів з використанням PUT
ж / If-None-Match: *
заголовка (або spec'ing правильні методи HTTP, см і MKCOL
т.д.).
Я не думаю, що відповідь на це була опублікована, хоча було багато чудових коментарів до існуючих відповідей. Я підняю суть цих коментарів до нової відповіді:
Цей абзац з RFC7231 був цитований кілька разів, що підсумовує його.
Корисне навантаження в повідомленні DELETE-запиту не має визначеної семантики; надсилання тіла корисного навантаження на запит DELETE може призвести до відхилення запиту в деяких існуючих реалізаціях.
Те, що я пропустив з інших відповідей, було наслідком. Так, дозволено включати тіло за DELETE
запитами, але це семантично безглуздо. Це насправді означає, що видача DELETE
запиту органу запиту семантично рівнозначна тому, що не включати орган запиту.
Включення органу запиту не повинно впливати на запит, тому ніколи не має сенсу його включати.
tl; dr: DELETE
Запит з тілом запиту дозволений, але це ніколи не корисно.
Якщо хтось стикається з тестуванням цього питання, Ні, це не підтримується повсюдно.
В даний час я тестую Sahi Pro, і дуже очевидно, що http DELETE виклику позбавляє будь-яких наданих даних про тіло (великий список ідентифікаторів, які потрібно видалити масово згідно з дизайном кінцевої точки).
Я контактував з ними декілька разів, а також надсилав у три окремі пакети сценаріїв, зображень, журналів для їх перегляду, і вони досі цього не підтвердили. Невдалий виправлення та пропущені конференц-дзвінки за їх підтримкою пізніше, і я все ще не отримав надійної відповіді.
Я впевнений, що Сахі не підтримує цього, і я думаю, що багато інших інструментів слідкують за набором.
Можливо, наведена нижче програма GitHUb допоможе вам отримати відповідь. Насправді сервер прикладних програм, як Tomcat, Weblogic відхиляє виклик HTTP.DELETE із завантаженням запиту. Отже, маючи на увазі всі ці речі, я додав приклад в github, будь ласка, погляньте на це