많은 항목을 삭제하는 편안한 방법


98

에서 REST에 대한 위키 기사 당신이 사용하는 경우 지적한다 http://example.com/resources 수단은 전체 컬렉션을 삭제하는 것을 삭제합니다.

http://example.com/resources/7HOU57Y DELETE 를 사용하는 경우 해당 요소를 삭제하는 것입니다.

웹 사이트를하고 있는데 웹 서비스가 아닙니다.

목록의 각 항목에 대해 1 개의 확인란이있는 목록이 있습니다. 삭제할 항목을 여러 개 선택하면 사용자가 DELETE SELECTION이라는 버튼을 누를 수 있습니다. 사용자가 버튼을 누르면 js 대화 상자가 팝업되어 사용자에게 삭제를 확인합니다. 사용자가 확인하면 모든 항목이 삭제됩니다.

그렇다면 RESTFUL 방식으로 여러 항목을 삭제하려면 어떻게해야합니까?

참고, 현재 웹 페이지에서 DELETE의 경우 POST와 함께 FORM 태그를 작업으로 사용하지만 DELETE 값이있는 _method를 포함하는 것입니다. 이것은 웹 페이지에 대한 RESTful 삭제를 수행하는 방법에 대해 SO에서 다른 사람들이 표시 한 것입니다 .


1
이러한 삭제를 원자 적으로 수행하는 것이 중요합니까? 31 일을 삭제할 수없는 경우 처음 30 개 항목의 삭제를 취소 하시겠습니까?
Darrel Miller

@darrelmiller 좋은 질문입니다. 나는 생각 삭제가 원자 적으로 실행되는 경우, 덜 효율적입니다. 따라서 DELETE FROM tablename WHERE ID IN ({list of ids})쪽으로 기울고 있습니다. 누군가가 이것이 좋은 생각인지 또는 나를 바로 잡는지를 지적 할 수 있다면. 잘 부탁드립니다. 또한 21 일이 삭제되면 처음 20 개 항목에 대해 삭제를 취소 할 필요가 없습니다. 내가 역을 필요로하는 곳에 누군가가 나에게 접근 방식의 차이를 보여줄 수 있다면 다시 나는 그것을 감사 대 내가 반대 할 필요가없는 경우
김 스택을

1
참고 : "IN"절에는 제한이있을 수 있습니다. 예를 들어, Oracle에서는 최대 1000 개의 ID를 넣을 수 있습니다.
rob

Google의 API 설계 가이드는 REST API에서 사용자 지정 (일괄) 작업을 생성하는 솔루션을 제공합니다. 여기 내 대답을 참조하십시오. stackoverflow.com/a/53264372/2477619
B12Toaster

답변:


54

지금까지로 조카의 대답 이 최고 라고 생각 합니다. 약간의 변형은 동일한 페이지에서 자바 스크립트 확인을 없애고 대신 선택 항목을 만들고 리디렉션하여 해당 페이지에 확인 메시지를 표시하는 것입니다. 다시 말해:

출처 :
http://example.com/resources/

~을하다

선택한 ID로 POST :
http://example.com/resources/selections

성공하면 다음과 같이 응답해야합니다.

HTTP / 1.1 201 생성 및 위치 헤더 :
http://example.com/resources/selections/DF4XY7

이 페이지에 (자바 스크립트) 확인 상자가 표시됩니다. 확인하면 다음을 요청합니다.

http://example.com/resources/selections/DF4XY7 삭제

성공하면 다음과 같이 응답해야합니다. HTTP / 1.1 200 Ok (또는 성공적인 삭제에 적합한 것)


리디렉션이 필요하지 않기 때문에이 아이디어가 마음에 듭니다. AJAX를 통합하면 페이지를 떠나지 않고도이 모든 작업을 수행 할 수 있습니다.
rojoca

이 DELETE example.com/resources/selections/DF4XY7 후에 example.com/resources로 다시 리디렉션됩니까?
Kim Stacks

7
@fireeyeboy이 두 단계 접근 방식은 일반적으로 다중 삭제를 수행하는 방법을 제안하는 것처럼 보이지만 그 이유는 무엇입니까? http://example.com/resources/selections/삭제하려는 항목에 대한 데이터를 보내는 요청의 페이로드 (본문)와 같은 URI에 DELETE 요청을 간단하게 보내지 않는 이유는 무엇입니까? 내가 말할 수있는 한, 당신이 이것을하는 것을 방해하는 것은 아무것도 없지만, 나는 항상 "그러나 그것은 RESTfull이 아니다"를 만난다.
thecoshman 2013-06-27

6
DELETE 잠재적 몸은 HTTP 기반 시설에 의해 무시 가질 수 있습니다 stackoverflow.com/questions/299628/...
누가 복음 Puplett

DELETE는 몸을 가질 수 있지만, 그 구현의 많은 기본적으로 몸을 금지
dmitryvim

54

한 가지 옵션은 삭제 "트랜잭션"을 만드는 것입니다. 그래서 당신 POSThttp://example.com/resources/deletes삭제할 자원 목록으로 구성된 새로운 자원 과 같은 것 입니다. 그런 다음 응용 프로그램에서 삭제를 수행하십시오. 게시를 할 때 생성 된 거래의 위치 (예 : http://example.com/resources/deletes/DF4XY7. 이에 대한 A GET는 트랜잭션의 상태 (완료 또는 진행 중) 및 / 또는 삭제할 리소스 목록을 반환 할 수 있습니다.


2
데이터베이스와 관련이 없습니다. 트랜잭션이란 수행 할 작업 목록을 의미합니다. 이 경우 삭제 목록입니다. 당신이하는 일은 애플리케이션의 리소스로 새 목록 (삭제 목록)을 만드는 것입니다. 웹 애플리케이션은 원하는대로 목록을 처리 할 수 ​​있습니다. 해당 리소스에는 URI (예 : example.com/resources/deletes/DF4XY7)가 있습니다. 즉, 해당 URI에 대한 GET을 통해 삭제 상태를 확인할 수 있습니다. 삭제를 수행 할 때 Amazon S3 또는 다른 CDN에서 이미지를 삭제해야하고 해당 작업을 완료하는 데 시간이 오래 걸릴 수있는 경우에 유용합니다.
rojoca 2010 년

2
+1 이것은 좋은 해결책입니다. 각 리소스에 DELETE를 보내는 대신 @rojoca는 유일한 작업이 리소스 목록을 삭제하는 새로운 유형의 리소스 인스턴스를 만들 것을 제안합니다. 예를 들어, 사용자 리소스 컬렉션이 있고 컬렉션에서 사용자 Bob, Dave 및 Amy를 삭제하려는 경우 생성 매개 변수로 Bob, Dave 및 Amy를 게시하는 새 삭제 리소스를 생성합니다. Deletion 리소스가 생성되고 사용자 컬렉션에서 Bob, Dave 및 Amy를 삭제하는 비동기 프로세스를 나타냅니다.
Mike Tunnicliffe

1
미안 해요. 여전히 몇 가지 문제를 이해하는 데 약간의 어려움이 있습니다. DF4XY7. 이 문자열을 어떻게 생성합니까? 이 삭제 리소스입니다. 데이터베이스에 데이터를 삽입해야합니까? 몇 가지 질문을 반복하면 사과드립니다. 나에게는 조금 낯설다.
Kim Stacks

1
DF4XY7이 생성 된 고유 ID라고 가정합니다. 예를 들어 example.com/resources/deletes/7과 같이 DB에 저장할 때 생성 된 ID 만 사용하는 것이 더 자연스러운 것일 수 있습니다. 필자는 삭제 모델을 생성하여 데이터베이스에 저장하고, 다른 레코드를 삭제하는 비동기 프로세스가 완료 상태 및 관련 오류로 삭제 모델을 업데이트하도록 할 수 있습니다.
Mike Tunnicliffe

2
@rojoca 예, 문제는 HTTP가 'DELETE는 단일 리소스를 제거하는 것'이라고 생각합니다. 당신이 무엇을하든, 여러 번 삭제하는 것은 약간의 해킹입니다. 이 작업이 진행 중이며 시간이 걸릴 수 있다는 클라이언트에게 '작업'을 반환 할 수 있지만이 URI를 사용하여 진행 상황을 확인합니다. 사양을 읽고 DELETE가 다른 요청과 마찬가지로 본문을 가질 수 있음을 확인했습니다.
thecoshman

33

Amazon이 S3 REST API로 수행 한 작업은 다음과 같습니다.

개별 삭제 요청 :

DELETE /ObjectName HTTP/1.1
Host: BucketName.s3.amazonaws.com
Date: date
Content-Length: length
Authorization: authorization string (see Authenticating Requests (AWS Signature Version 4))

다중 객체 삭제 요청 :

POST /?delete HTTP/1.1
Host: bucketname.s3.amazonaws.com
Authorization: authorization string
Content-Length: Size
Content-MD5: MD5

<?xml version="1.0" encoding="UTF-8"?>
<Delete>
    <Quiet>true</Quiet>
    <Object>
         <Key>Key</Key>
         <VersionId>VersionId</VersionId>
    </Object>
    <Object>
         <Key>Key</Key>
    </Object>
    ...
</Delete>           

그러나 Facebook Graph API , Parse Server REST APIGoogle Drive REST API 는 한 번의 요청으로 개별 작업을 "일괄 처리"할 수 있도록함으로써 훨씬 더 나아갑니다.

다음은 Parse Server의 예입니다.

개별 삭제 요청 :

curl -X DELETE \
  -H "X-Parse-Application-Id: ${APPLICATION_ID}" \
  -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
  https://api.parse.com/1/classes/GameScore/Ed1nuqPvcm

일괄 요청 :

curl -X POST \
  -H "X-Parse-Application-Id: ${APPLICATION_ID}" \
  -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
        "requests": [
          {
            "method": "POST",
            "path": "/1/classes/GameScore",
            "body": {
              "score": 1337,
              "playerName": "Sean Plott"
            }
          },
          {
            "method": "POST",
            "path": "/1/classes/GameScore",
            "body": {
              "score": 1338,
              "playerName": "ZeroCool"
            }
          }
        ]
      }' \
  https://api.parse.com/1/batch

13

DELETE http://example.com/resources/id1,id2,id3,id4 또는 DELETE http://example.com/resources/id1+id2+id3+id4 라고 말합니다 . 이 위키피디아 기사를 인용하는 "REST는 아키텍처 (...) [아님] 프로토콜"이므로이를 수행하는 단일 방법이 없다고 생각합니다.

HTML을 사용하는 JS 없이는 위의 작업이 불가능하다는 것을 알고 있지만 REST가 다음과 같은 느낌을받습니다.

  • 거래와 같은 사소한 세부 사항을 생각하지 않고 만들어졌습니다. 누가 더 많은 단일 항목을 조작해야합니까? 이것은 정적 웹 페이지 이외의 다른 것을 통해 제공하도록 의도되지 않았기 때문에 HTTP 프로토콜에서 정당화됩니다.
  • 순수한 HTML 일지라도 현재 모델로 잘 조정할 필요는 없습니다.

thx-전체 컬렉션을 삭제하려면 어떻게해야합니까? ID를 생략해야합니까?
BKSpurgeon

"나는 REST가 ... 트랜잭션과 같은 사소한 세부 사항을 생각하지 않고 만들어 졌다는 느낌을받습니다."– 그것은 사실이라고 생각하지 않습니다. 내가 올바르게 이해하면 REST에서 트랜잭션은 메서드가 아닌 리소스로 표시됩니다. 이 블로그 게시물에 대한이 의견에서 절정에 이르는 좋은 토론 있습니다.
Paul D. Waite

10

흥미롭게도 여러 엔터티를 PATCH하는 것과 동일한 방법이 적용되며 URL, 매개 변수 및 REST 메서드에서 의미하는 바를 고려해야합니다.

  1. 모든 'foo'요소를 반환합니다.

    [GET] api/foo

  2. 특정 ID를 필터링하여 'foo'요소를 반환합니다.

    [GET] api/foo?ids=3,5,9

여기서 의미는 URL과 필터가 "우리가 다루는 요소는 무엇입니까?"를 결정하고 REST 메서드 (이 경우 "GET")는 "이러한 요소로 무엇을해야합니까?"라고 말합니다.

  1. 따라서 여러 레코드를 PATCH하여 읽은 것으로 표시합니다.

    [PATCH] api/foo?ids=3,5,9

.. 데이터 foo [read] = 1

  1. 마지막으로 여러 레코드를 삭제하려면이 끝 점이 가장 논리적입니다.

    [DELETE] api/foo?ids=3,5,9

나는 이것에 대해 어떤 "규칙"이 있다고 믿지 않는다는 것을 이해하십시오.


실제로 PATCH 와 관련하여 : 엔티티 목록을 엔티티 자체 (배열 유형의 경우에도)로 생각하면 부분 업데이트를 의미하기 때문에 부분 엔티티의 부분 배열 (업데이트하려는 ID 만)을 전송하면 쿼리 문자열을 생략 할 수 있으므로 둘 이상의 항목을 나타내는 URL이 없습니다.
Szabolcs Páll

2

으로 점잖은 물장난 응답rojocas 대답은 말한다, 가장 표준적인 자원의 선택을 삭제하는 가상 리소스를 사용하지만, 난을 실행하는 것이 있기 때문에 그하는 REST 관점에서 잘못 생각하는 DELETE http://example.com/resources/selections/DF4XY7선택의 자원 자체가 아니라 선택된 자원을 제거해야합니다.

복용 마치에이 Piechotka의 anwser 또는 fezfox 응답을 , 난 단지 이의가 :이 ID의 배열을 전달보다 표준 방법, 그리고 배열 연산자를 사용하고 있습니다 :

DELETE /api/resources?ids[]=1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d&ids[]=7e8f9a0b-1c2d-3e4f-5a6b-7c8d9e0f1a2b

이런 식으로 컬렉션 삭제 끝점을 공격하지만 올바른 방법으로 쿼리 문자열을 사용하여 삭제를 필터링합니다.


-1

이를 수행하는 '적절한'방법이 없기 때문에 내가 과거에 한 일은 다음과 같습니다.

http://example.com/something에 DELETE를 보냅니다 .본문에 xml 또는 json으로 인코딩 된 데이터와 함께 으로 보냅니다.

요청을 받으면 DELETE를 확인하고 true이면 삭제할 본문을 읽습니다.


이것은 나에게 의미가있는 접근 방식입니다. 여러분은 단순히 하나의 요청으로 데이터를 보내지 만 저는 항상 "하지만 RESTfull이 아닙니다"를 만납니다. 이것이 실행 가능하고 'RESTfull'방법이라고 제안하는 출처가 있습니까?
thecoshman

10
이 접근 방식의 문제점은 DELETE 작업이 본문을 기대하지 않기 때문에 인터넷의 일부 중간 라우터가 사용자의 제어 나 지식없이이를 제거 할 수 있다는 것입니다. 따라서 DELETE에 body를 사용하는 것은 안전하지 않습니다!
Alex White

알렉스의 의견에 대한 참조 : stackoverflow.com/questions/299628/...
누가 복음 Puplett

1
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.에서 tools.ietf.org/html/rfc7231#section-4.3.5
cottton

-1

여러 항목을 삭제하는 동일한 상황이 발생했습니다. 이것이 내가 한 일입니다. DELETE 작업을 사용했고 삭제 될 항목의 ID는 HTTP 헤더의 일부였습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.