HTTP DELETE 요청을 발행 할 때 요청 URI는 삭제할 자원을 완전히 식별해야합니다. 그러나 요청의 엔터티 본문의 일부로 추가 메타 데이터를 추가 할 수 있습니까?
HTTP DELETE 요청을 발행 할 때 요청 URI는 삭제할 자원을 완전히 식별해야합니다. 그러나 요청의 엔터티 본문의 일부로 추가 메타 데이터를 추가 할 수 있습니까?
답변:
사양 은 명시 적으로 금지하거나 권장하지 않으므로 허용된다고 말하는 경향이 있습니다.
Microsoft는 동일한 방식으로 (청중의 불평 소리를들을 수 있음) MSDN 문서 에서 AELE.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.
따라서 이전 버전과의 호환성 경고가 제공되므로 다음 표준에서 다음과 같이 말할 것입니다. 'yep! 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
각 메시지에는 고유 한 버전이 있습니다. 여러 헤더를 사용하여 여러 버전을 지정할 수도 있지만 George가 더 간단하고 편리합니다.
이것은 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에서 :
요청에 메시지 본문이 존재한다는 것은 요청의 메시지 헤더에 Content-Length 또는 Transfer-Encoding 헤더 필드를 포함시킴으로써 알 수 있습니다. 요청 방법 (5.1.1 절)의 명세가 엔티티 본문을 요청으로 전송하는 것을 허용하지 않는다면, 메시지 본문은 요청에 포함되어서는 안된다 (MUST NOT). 서버는 요청시 메시지 본문을 읽고 전달해야합니다. 요청 방법에 엔티티 본문에 대해 정의 된 의미가 포함되어 있지 않으면 요청을 처리 할 때 메시지 본문을 무시해야합니다.
섹션 9.7 :
DELETE 메소드는 오리진 서버가 Request-URI로 식별 된 자원을 삭제하도록 요청합니다. 이 방법은 오리진 서버에서 사람의 개입 (또는 다른 수단)에 의해 무시 될 수 있습니다. 오리진 서버에서 리턴 된 상태 코드가 조치가 완료되었음을 표시하더라도 클라이언트는 조작이 수행되었음을 보증 할 수 없습니다. 그러나 서버는 응답이 제공 될 때 리소스를 삭제하거나 액세스 할 수없는 위치로 이동시키지 않는 한 성공을 나타내서는 안됩니다.
응답에 상태를 설명하는 엔터티가 포함 된 경우 성공적인 응답은 200 (OK)이고, 조치가 아직 시행되지 않은 경우 202 (Accepted), 조치가 시행되었지만 응답이 포함되지 않은 경우 204 (No Content) 여야합니다. 실체.
요청이 캐시를 통과하고 Request-URI가 현재 캐시 된 하나 이상의 엔티티를 식별하는 경우 해당 항목은 오래된 것으로 취급해야합니다. 이 방법에 대한 응답은 캐시 할 수 없습니다 .c
따라서 명시 적으로 허용되거나 허용되지 않으며, 진행중인 프록시가 메시지 본문을 제거 할 가능성이 있습니다 (읽고 전달해야하지만).
DELETE 요청에 본문을 제공하고 Google 클라우드 HTTPS로드 밸런서를 사용하는 경우 400 오류로 요청이 거부됩니다. 나는 벽에 머리를 대고 있었고, 구글은 어떤 이유로 든 몸에 대한 삭제 요청이 잘못된 요청이라고 생각했다.
for whatever reason
-스펙이 그렇게
DELETE
것이 후자입니다.
ElasticSearch가 다음을 사용하는 것 같습니다. https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Netty가이를 지원한다는 의미입니다.
의견에서 언급했듯이 더 이상 그렇지 않을 수 있습니다.
HTTP 메일 링리스트의 Roy Fielding은 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 / objects / 모든 객체를 얻습니다
GET / 개체 / ID 지정된 ID를 가진 개체를 가져옵니다.
POST / objects 새 객체를 추가합니다
PUT / object / ID 지정된 ID의 객체를 추가하고 객체를 업데이트합니다
DELETE / object / ID 지정된 ID를 가진 개체를 삭제합니다.
모든 사용자 지정 작업은 POST입니다
POST / objects / addList 본문에 포함 된 객체의 목록 또는 배열을 추가합니다
POST / objects / deleteList 본문에 포함 된 객체 목록을 삭제합니다.
POST / objects / customQuery 본문의 사용자 지정 쿼리를 기반으로 목록을 만듭니다.
클라이언트가 확장 작업을 지원하지 않으면 정기적으로 작동 할 수 있습니다.
POST
POST 응답의 의미가 명확하지 않기 때문에, 특히 Location 헤더와 관련 하여 a를 사용하는 것은 새로운 리소스를 만드는 데 RESTA 한 방법이 아닙니다. 본질적으로 HTTP를 남겨두고 RPC를 맨 위에 둡니다. 올바른 "HTTP / REST 방식"은 헤더를 사용하여 자원을 작성 PUT
하는 것입니다 If-None-Match: *
(또는 적절한 HTTP 메소드 지정, MKCOL
기타 참조 ).
기존 답변에 대한 많은 의견이 있었지만 이것에 대한 좋은 답변이 게시되지 않았다고 생각합니다. 나는 그 의견의 요지를 새로운 답변으로 들어 올릴 것입니다.
RFC7231의이 단락은 몇 번 인용되어 요약됩니다.
DELETE 요청 메시지 내의 페이로드에는 정의 된 의미가 없습니다. DELETE 요청에서 페이로드 본문을 전송하면 일부 기존 구현에서 요청을 거부 할 수 있습니다.
다른 답변에서 놓친 것은 그 의미입니다. 예 DELETE
, 요청시 본문을 포함 할 수 있지만 의미 상 의미가 없습니다. 이것이 실제로 의미하는 것은 DELETE
요청 본문 으로 요청 을 발행하는 것이 의미 적으로 요청 본문을 포함하지 않는 것과 같습니다.
요청 본문을 포함하면 요청에 영향을 미치지 않아야하므로 요청을 포함시킬 필요가 없습니다.
tl; dr : 기술적으로 DELETE
요청 본문이있는 요청은 허용되지만 그렇게하는 것은 결코 유용하지 않습니다.
이 문제 테스트에 참여한 사람이있는 경우 아니요. 보편적으로 지원되지 않습니다.
나는 현재 Sahi Pro로 테스트 중이며 http DELETE 호출은 제공된 바디 데이터 (끝점 디자인에 따라 대량으로 삭제되는 많은 ID 목록)를 제거합니다.
나는 그들과 여러 번 접촉을했고 검토 할 수 있도록 스크립, 이미지, 로그의 세 가지 개별 패키지로 보냈지 만 여전히 이것을 확인하지 못했습니다. 실패한 패치와 부재중 전화 회의는 나중에 지원을 통해 전화를 걸었지만 여전히 확실한 대답을 얻지 못했습니다.
나는 Sahi가 이것을 지원하지 않는다고 확신하며, 다른 많은 도구가 제품군을 따르는 것을 상상할 것입니다.
아래 GitHUb URL이 도움이 될 것입니다. 실제로 Tomcat과 같은 Application Server는 Weblogic에서 요청 페이로드로 HTTP.DELETE 호출을 거부합니다. 이 모든 것을 명심하고 github에 예제를 추가했습니다.