DELETE 요청 본문에 대한 RESTful 대안


93

그동안 HTTP 1.1 사양이 보인다 에 메시지 본문 DELETE 요청을,에 대한 정의 의미가 없기 때문에 서버가 그것을 무시해야 함을 표시 것으로 보인다.

4.3 메시지 본문

서버는 모든 요청에 ​​대해 메시지 본문을 읽고 전달해야합니다. 요청 메소드가 엔티티 본문에 대해 정의 된 의미를 포함하지 않는 경우 요청을 처리 할 때 메시지 본문을 무시해야합니다 (SHOULD).

나는 이미 다음과 같은이 주제에 대한 몇 가지 관련 토론을 검토했습니다.

대부분의 토론은 DELETE에 메시지 본문을 제공하는 것이 허용 있다는 데 동의하는 것처럼 보이지만 일반적으로 권장되지 않습니다.

또한 DELETE에서 요청 본문을 지원하기 위해 이러한 라이브러리에 대해 점점 더 많은 개선 사항이 기록되는 것처럼 보이는 다양한 HTTP 클라이언트 라이브러리의 추세를 확인했습니다. 대부분의 도서관은 의무가있는 것처럼 보이지만 때로는 약간의 초기 저항이 있습니다.

내 사용 사례에서는 DELETE에 필요한 메타 데이터를 추가해야합니다 (예 : 삭제에 필요한 다른 메타 데이터와 함께 삭제 "이유"). 다음 옵션을 고려했지만 HTTP 사양 및 / 또는 REST 모범 사례와 완전히 적절하고 인라인 된 것은 없습니다.

  • 메시지 본문 -사양은 DELETE의 메시지 본문에 의미 값이 없음을 나타냅니다. HTTP 클라이언트에서 완전히 지원되지 않습니다. 표준 관행이 아님
  • 사용자 지정 HTTP 헤더 -사용자 지정 헤더를 요구하는 것은 일반적으로 표준 관행에 위배됩니다 . 그것들을 사용하는 것은 내 API의 나머지 부분과 일치하지 않으며 사용자 지정 헤더가 필요하지 않습니다. 또한 잘못된 사용자 정의 헤더 값을 나타내는 데 사용할 수있는 좋은 HTTP 응답이 없습니다 (아마도 별도의 질문 일 것입니다).
  • 표준 HTTP 헤더 -적절한 표준 헤더 없음
  • 쿼리 매개 변수 - 쿼리 매개 변수를 추가하면 실제로 삭제되는 요청 URI가 변경됩니다. 표준 관행에 반하여
  • POST 방법 -(예 POST /resourceToDelete { deletemetadata }) POST는 삭제를위한 의미 론적 옵션이 아닙니다. POST는 실제로 원하는 반대 동작을 나타냅니다 (예 : POST는 리소스 부하를 생성하지만 리소스를 삭제해야 함).
  • 다중 메소드 -DELETE 요청을 두 개의 작업으로 분할 (예 : PUT 삭제 메타 데이터, 다음 DELETE)하면 원자 적 작업이 두 개로 분할되어 잠재적으로 일관성없는 상태가 남습니다. 삭제 이유 (및 기타 관련 메타 데이터)는 리소스 표현 자체의 일부가 아닙니다.

내 첫 번째 선호도는 아마도 사용자 정의 HTTP 헤더에 이어 메시지 본문을 사용하는 것입니다. 그러나 표시된대로 이러한 접근 방식에는 몇 가지 단점이 있습니다.

DELETE 요청에 필요한 메타 데이터를 포함하기위한 REST / HTTP 표준과 관련된 권장 사항 또는 모범 사례가 있습니까? 고려하지 않은 다른 대안이 있습니까?


2
같은 특정 구현 Jerseydelete요청 본문을 허용하지 않습니다 .
basiljames

답변:


44

DELETE 요청에 메시지 본문을 사용하지 말라는 몇 가지 권장 사항에도 불구하고이 접근 방식은 특정 사용 사례에 적합 할 수 있습니다. 이것은 우리가 질문 / 답변에 언급 된 다른 옵션을 평가하고 서비스 소비자와 협력 한 후에 사용한 접근 방식입니다.

메시지 본문의 사용이 이상적이지는 않지만 다른 옵션 중 어느 것도 완벽하게 적합하지 않았습니다. 요청 본문 DELETE를 사용하면 DELETE 작업을 수반하는 데 필요한 추가 데이터 / 메타 데이터에 대한 의미 체계를 쉽고 명확하게 추가 할 수 있습니다.

나는 여전히 다른 생각과 토론에 열려 있지만이 질문에 대한 루프를 닫고 싶었습니다. 이 주제에 대한 모든 사람의 생각과 토론에 감사드립니다!


12
이것은 나쁜 생각입니다. 이로 인해 문제가 발생하는 한 곳은 나중에 Akamai EdgeConnect와 같은 HTTP 가속화 서비스를 사용하기로 결정한 경우입니다. EdgeConnect가 HTTP DELETE 요청에서 본문을 제거한다는 사실을 알고 있습니다 (대역폭을 사용하는 것이 유효하지 않을 가능성이 있기 때문입니다). 유사한 서비스도 동일하게 작동 할 가능성이 높습니다 (Kindle의 가속 기능 및 기타 CDN 유사 서비스 참조). 서비스에 HTTP 동사를 사용하지 않도록 다시 디자인해야합니다. 대부분의 API는 HTTP-verbs / classical-REST를 사용하는 것이 거의 의미가 없으며 HTTP 동사 전송 문제는 해결하기가 매우 어렵습니다.
Gabe

3
@Gabe와 동의 합니다. 정의 에 따라 본문이없는 메서드로 본문을 보내는 것은 비트가 인터넷 파이프를 통과 할 때 데이터를 무작위로 잃는 확실한 방법이며 디버깅하는 데 매우 어려울 것입니다.
Nicholas Shanks 2014 년

3
DELETE 사용에 대한 이러한 의견은 OP가 가진 매우 유효한 문제를 해결할 때까지 관련이 없습니다. 나는 REST의 정신을 고수하기 위해 최선을 다하고 있지만 낙관적 동시성이없는 삭제와 원자 적 일괄 작업이없는 삭제는 실제 상황에서 실용적이지 않습니다. 이것은 REST 패턴의 심각한 결함입니다.
Quarkly

나는 이것에 대해 @Quarkly와 함께 있습니다. 동시성 등을 확인하는 방법에 대한 RESTFUL 아이디어가 무엇인지 이해하지 못합니다. 동시성 검사는 클라이언트에 속하지 않습니다.
Dirk Wessels

13

당신이 원하는 것은 두 가지 중 하나입니다 DELETE.

  1. 두 가지 작업이 있습니다 . PUT하나는 삭제 이유이고 그 뒤에는 DELETE하나의 리소스가 있습니다. 삭제 된 리소스의 내용은 더 이상 누구에게도 액세스 할 수 없습니다. '이유'에는 삭제 된 리소스에 대한 하이퍼 링크가 포함될 수 없습니다. 또는,
  2. 당신은 자원 변경하려는 에서 state=active로를 state=deleted사용하여 DELETE방법을. state = deleted 인 리소스는 기본 API에서 무시되지만 관리자 또는 데이터베이스 액세스 권한이있는 사람은 여전히 ​​읽을 수 있습니다. 이는 허용됩니다 DELETE. 리소스에 대한 백업 데이터를 지울 필요가 없으며 해당 URI에 노출 된 리소스 만 제거 할 수 있습니다.

메시지 본문이 필요한 모든 작업 DELETE요청POST 이 필요한 모든 작업은 가장 일반적으로, 메시지 본문으로 필요한 모든 작업을 수행하는 작업과 DELETE. HTTP의 의미를 깨뜨릴 이유가 없습니다.


2
PUT이유가 성공하고 DELETE리소스가 실패 하면 어떻게됩니까 ? 불일치 상태를 어떻게 방지 할 수 있습니까?
라이트

1
@Lightman PUT는 의도 만 지정합니다. 해당 DELETE없이 존재할 수 있습니다. 이는 누군가가 삭제를 원했지만 실패했거나 마음이 바뀌 었음을 나타냅니다. 호출 순서를 반대로하면 이유없이 DELETE가 발생할 수 있습니다. 이유 제공은 단순히 주석으로 간주됩니다. 위의 옵션 2를 사용하는 것이 좋습니다. 즉, HTTP 리소스가 현재 URL에서 사라지도록하는 것과 같은 기본 레코드의 상태를 변경하는 것이 좋습니다. 가비지 컬렉터 / 관리자는 기록을 제거 할 수 있습니다
니콜라스 정강이

7

상황을 감안할 때 다음 접근 방식 중 하나를 사용합니다.

  • PUT 또는 PATCH 보내기 : 삭제 이유가 필요한 특성상 삭제 작업이 가상이라고 추론하고 있습니다. 따라서 PUT / PATCH 작업을 통해 레코드를 업데이트하는 것은 DELETE 작업 자체는 아니지만 유효한 방법이라고 생각합니다.
  • 쿼리 매개 변수 사용 : 리소스 URI가 변경되지 않습니다. 나는 이것이 또한 유효한 접근이라고 생각합니다. 연결 한 질문은 쿼리 매개 변수가 누락 된 경우 삭제를 허용하지 않는 것에 대한 것입니다. 귀하의 경우에는 이유가 쿼리 문자열에 지정되지 않은 경우 기본 이유가 있습니다. 리소스는 여전히 resource/:id. 각 이유에 대해 리소스의 링크 헤더를 사용하여 검색 가능하게 만들 수 있습니다 (각 이유 rel를 식별 하는 태그 포함).
  • 이유에 따라 별도의 엔드 포인트 사용 과 같은 URL을 사용을 : resource/:id/canceled. 이것은 실제로 Request-URI를 변경하며 확실히 RESTful이 아닙니다. 다시 말하지만, 링크 헤더는이를 검색 가능하게 만들 수 있습니다.

REST는 법이나 교리가 아님을 기억하십시오. 지침으로 더 생각하십시오. 따라서 문제 영역에 대한 지침을 따르지 않는 것이 합리적 일 때 그렇게하지 마십시오. API 소비자에게 차이를 알려주십시오.


쿼리 매개 변수 사용과 관련하여 쿼리가 섹션 3.2 에 따라 Request-URI의 일부 이므로이 접근 방식 (또는 마찬가지로 별도의 끝점)을 사용하면 DELETE 메서드 의 정의에 위배 됩니다. Request-URI로 식별 "이 삭제됩니다.
shelley

리소스는 uri 경로로 식별됩니다. 따라서 GET to /orders/:id/orders/:id?exclude=orderdetails. 쿼리 문자열은 서버에 힌트 만 제공합니다.이 경우 응답에서 orderdetails를 제외합니다 (지원되는 경우). 마찬가지로 /orders/:id또는 /orders/:id?reason=canceled또는 로 DELETE를 보내는 경우 /orders/:id?reason=bad_credit에도 여전히 동일한 기본 리소스에서 작업하고 있습니다. '균일 한 인터페이스'를 유지하려면 쿼리 매개 변수를 보낼 필요가없는 기본 이유가 있습니다.
codeprogression 2013 년

@shelley 쿼리 문자열에 대한 우려 사항이 맞습니다. 쿼리 문자열은 URI의 일부입니다. 에 DELETE 요청 /foo?123을 보낸다는 것은 DELETE를에 보내는 경우와 다른 리소스를 삭제한다는 의미 /foo?456입니다.
Nicholas Shanks

@codeprogression 죄송합니다. 말씀하신 내용의 대부분이 잘못되었습니다. 리소스는 경로뿐만 아니라 전체 URI로 식별됩니다. 다른 쿼리 문자열은 다른 리소스입니다 ( 'resource'라는 단어의 HTTP 의미에서). 또한 균일 한 인터페이스에는 기본 이유가 필요하지 않습니다. 이 용어는 HTTP가 정의한 방식으로 GET, PUT, POST, PATCH 및 DELETE를 사용하는 것을 의미합니다. 공통점은 공급 업체 (사용자 에이전트 공급 업체, API 공급 업체, 캐싱 프록시 공급 업체, ISP 등) 사이에 있으며 자체 API 내에 있지 않습니다 (사용자의 온전함을 위해 디자인에서 균일해야합니다!).
Nicholas Shanks

@Nicholas 나는 3 년 전에 끝난 토론에 대해 당신이 논쟁해야 할 필요성을 이해하지 못합니다. 내가 작성한 답변과 의견은 REST 중심보기에서 유효하고 정확합니다. REST는 HTTP (또는 HTTP의 공급 업체 구현)가 아닙니다. REST의 맥락에서 리소스는 동일합니다. 그리고 내 대답에서 말했듯이 REST는 법이나 교리가 아니라 지침입니다.
codeprogression

0

필요한 메타 데이터를 URI 계층 자체의 일부로 포함하는 것이 좋습니다. 예 (순진한) :

날짜 범위를 기준으로 항목을 삭제해야하는 경우 시작 날짜와 종료 날짜를 본문 또는 쿼리 매개 변수로 전달하는 대신 URI의 일부로 필요한 정보를 전달하는 방식으로 URI를 구성합니다.

예 :

DELETE /entries/range/01012012/31122012 -2012 년 1 월 1 일부터 2012 년 12 월 31 일 사이의 모든 항목 삭제

도움이 되었기를 바랍니다.


5
삭제 이유, 즉 댓글 필드를 보내는 것과 같은 경우는 다루지 않습니다.
Kugel

3
와. 끔찍한 생각입니다. 메타 데이터가 너무 많으면 URI의 크기 제한이 커집니다.
Balaji Boggaram Ramanarayan

1
이 접근 방식은 RESTful 방식을 따르지 않으며 복잡한 URI 구조를 갖게되므로 권장되지 않습니다. 엔드 포인트는 얽힌 리소스 식별과 메타 데이터로 뒤죽박죽이되며 API가 변경됨에 따라 시간이 지나면 유지 관리의 악몽이 될 것입니다. 이 range질문의 핵심 인 쿼리 매개 변수 또는 페이로드에 지정 하는 것이 훨씬 더 선호됩니다 . 내가 말하는 문제에 대한 모범 사례 접근 방식을 이해하려면 이것이 아닙니다.
digitaldreamer

@digitaldreamer-복잡한 URI 구조가 의미하는 바를 이해하지 못합니까? 또한 이것은 HTTP DELETE이므로 페이로드는 옵션이 아니라 쿼리 매개 변수 예입니다.
수레 쉬 쿠마르
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.