PUT 또는 DELETE로 컬렉션을 부분적으로 변경해도 괜찮습니까?


21

제품 그룹에 제품 모음이 있습니다. 예 :

product-groups/123/products
  1. 컬렉션 에 추가 해야하는 경우 PUT이있는 일부 제품 만 전달해도 괜찮 습니까?

  2. 컬렉션에서 일부 제품 을 삭제해야하는 경우 DELETE를 사용하여 필터 데이터 (ID 배열)를 전달해도 괜찮 습니까?

ReST의 정신으로 기능을 구현하는 가장 좋은 방법은 무엇입니까?

편집 : 항목은 기본적으로 제품의 ID 인 개별 엔티티에 대한 링크입니다.


제품 그룹의 항목이 다른 곳에서 관리되는 자원입니까? 아니면은 단지 제품 그룹의 컬렉션의 일부? 별도의 제품이 여러 제품 그룹에 속할 수 있습니까?
Martijn Pieters

2
아마도 PATCH 이 규격은 새로운 HTTP / 1.1 [RFC2616] 방법 인 PATCH를 정의하는데, 이것은 자원에 부분적인 수정을 적용하는데 사용된다.
Esailija

제품 (ID)은 여러 제품 그룹에 속할 수 있습니다.
user151851

컬렉션에 제품을 추가하거나 삭제하는 방법을 말하는 잘 알려진 방법 (모범 사례)이 있습니까?
user151851

답변:


10

일반적으로 x 의 전체 콜렉션을 나타내는 하나의 엔드 포인트가 있습니다 .

/products

예를 들어 단일 제품을 업데이트하고 PUT 을 만드십시오 /products/{id}. 모든 제품을 업데이트하지 않고 단일 제품을 부분적으로 업데이트하려는 경우 PATCH to를 사용할 수도 있습니다 /products/{id}. 단일 엔티티의 삭제도 마찬가지입니다 ( DELETE to /products/{id}).

단일 리소스 를 대상으로하려는 경우 경로를 통해 단일 리소스를 수정할 수 있습니다.

계획을 어기는 유일한 행동 은 자원을 만드는 것 입니다. 리소스를 생성 할 때 컬렉션 전체를 대상으로합니다 ( POST to) /products.

즉, 전체적으로 컬렉션에 영향을 미치는 작업의 대상이 적절한 컬렉션 엔드 포인트로 이동해야한다는 것이 분명해야합니다.

예를 들어 빨간색 인 제품의 하위 집합을 검색하려는 경우

GET/products?colour=red.

따라서 이러한 모든 항목을 삭제하려면 DELETE /products?colour=red 입니다. 당신을 통해 제품의 일부를 삭제하려는 경우 또는 id, 당신은 할 수 삭제 /products?id=1&id=2&id=3 .

무엇에 대한 대량 생성 능숙의? POST 컬렉션을 [{...},{...},{...}]단순히 /products. PUTPATCH도 마찬가지 입니다.

정말 간단합니다.

질문에 대답하려면 :

컬렉션에 추가해야하는 경우 PUT이있는 일부 제품 만 전달해도 괜찮습니까?

그것은 괜찮을뿐만 아니라 그렇게하는 것이 좋습니다.

컬렉션에서 일부 제품을 삭제해야하는 경우 DELETE를 사용하여 필터 데이터 (ID 배열)를 전달해도 괜찮습니까?

괜찮아. Eneko 알론소가 썼던 것처럼, 때로는 거기에 bulkoperations 즉, "컨트롤러"-endpoints를 통해 캡슐화 된 POST가 트리거 (복합) 작업에 사용됩니다.


2
PUT은 교체 작업입니다. "일부 제품"으로 콜렉션 엔드 포인트에서 PUT을 호출하면 "일부 제품"목록에 포함되지 않은 모든 제품을 삭제해야합니다 (OP의 경우 관계를 삭제해야 함). 항목을 추가하는 데 사용할 수 있지만 OP가 기대하지 않는 항목도 제거해야합니다. 첫 질문에 대한 답변을 적절히 수정해야합니다.
claytond

@claytond : 부분 업데이트가을 통해 완료되고을 PATCH통해 완전히 교체 되는 한 대답이 훌륭하다고 생각합니다 PUT.
9000

4
@ 9000. 물론, 그러나 대답은 현재 "당신은 컬렉션에 추가하는 것이 좋습니다 ... PUT이있는 일부 제품 만 통과"합니다. 확실하지 않습니다. POST에 격려했습니다. 퍼팅 가능하지만 모든 아이템이 아닌 일부만 전달해야합니다.
claytond

5

일반적으로 REST 메소드는 단일 엔티티 / 객체 (CRUD)에서 작동하도록되어 있습니다.

몇 가지 옵션이 있습니다.

  • 컬렉션을 엔티티로 취급하고 POST를 통해 업데이트
  • REST가 아닌 대체 조작 작성

첫 번째는 REST 표준을 따르지만 콜렉션 오브젝트 / 엔티티가 매우 클 수 있으므로 비용이 많이들 수 있습니다 (하나의 제품을 추가 / 제거하기 위해 수천 개의 제품이있는 그룹을 업데이트하면 많은 요청이 발생 함).

두 번째 옵션은 CRUD 조작 이상으로 REST를 확장하는 방법으로 많은 API에서 선호합니다.

예를 들면 다음과 같습니다.

GET product-groups/123/products (list all the products in the group)
POST product-groups/123/products/append (POST a list of new product ids to append to the group)
POST product-groups/123/products/remove (POST a list of product ids to remove from the group)

많은 API는이 확장 조작에 항상 POST를 사용하지만 다른 http 메소드 (빈 본문을 갖기위한 GET 및 DELETE의 제한을 제외 함)를 사용하도록 제한하는 것은 없습니다.


물론 목표를 달성하기위한 몇 가지 방법이 있습니다. 가장 좋은 방법은 무엇입니까? 어느 것이 더 미래에 대비할 것인가?
user151851

4
@ user151851 : 전체 REST 준수 (이러한 경우)는 높은 목표입니다. 여기에서 접근 방식은 실제로 "실제 세계"에서 실제로 사용되는 접근 방식을 사용하려고하므로 사실상 현실적으로 보입니다. 사실상 사실상 표준입니다. 그것은 당신이 얻을만큼 미래에 대한 것입니다.
Robert Harvey

2
URL에 "append"와 "delete"를 사용하여 커스텀 동사를 소개하지 않습니까? 그런 식으로 API 사용 방법을 설명해야합니다. 우리가 가지고있는 것을 즉, HTTP 메소드를 재사용해서는 안됩니까? 어떤 경우에는 동작이 잘 알려져 있습니다.
user151851

7
이 답변에 발생하는 다른 사람을 위해 : 그것은 잘못입니다. @ user151851에서 언급했듯이, URL에 동사를 소개합니다. 실제 질문과 관련하여 나는 큰 대답을하지는 못했지만 이것이 아닙니다.
umbrae

products/collection항목의 '봉투'를 반환하고 봉투 내용이 PUT을 통해 변경 되어 "확장"이보다 자원 지향적 일 수 있습니까? "컬렉션에있는 항목을 정확히 원하는 방법"과 같습니다.
Luke Puplett

3

정확한 이전 답변 / 의견에.

내 지식에 따르면 POST는 컬렉션에 단일 요소를 추가하는 방법입니다.

DELETE는 컬렉션에서 단일 요소를 삭제하는 방법입니다. 두 시나리오 모두 완벽하게 RESTful입니다.

그러나 단일 요소 또는 전체 컬렉션을 참조하려면 적절한 URI를 사용해야합니다.

예를 들어 컬렉션에 요소를 추가하려면 데이터를 다음 URI에 POST해야합니다.

https://www.factory.net/products/

컬렉션에서 단일 제품을 삭제하려면 DELETE 메서드를 사용하여 다음과 같은 요청을 보낼 수 있습니다.

https://www.factory.net/products/108/

PATCH 메서드를 사용하면 컬렉션 내의 일부 요소를 업데이트 할 수 있습니다. 예를 들어 한 요소에서 하나의 필드 만 업데이트해야하는 경우. 매우 큰 컬렉션에 대해 완전한 리소스 표현을 퍼팅하는 것은 비용이 많이 드는 작업 일 수 있습니다.


2

원칙적으로 모든 RESTful 조작은 콜렉션에서 유효하지만 동사의 의미가 콜렉션에 적용되는 방법을 이해해야합니다.

  • PUT은 완전한 대체품입니다.

    • 싱글 톤 (예 :)에 PUT을 /item/{id}남겨두고 name나가면이를 지우거나 null 또는 이와 유사한 것으로 설정해야합니다.
    • 컬렉션에 PUT을 추가하고 항목을 포함하지 않으면 해당 컬렉션에서 해당 항목을 제거 해야합니다 .

    PUT을 사용하여 항목을 추가 할 수 있지만 "모든"항목을 보내야합니다. "일부"항목을 보내면 제거해야합니다 (OP가 원치 않는 것으로 가정).

  • DELETE가 더 직관적입니다. 콜렉션 또는 필터링 된 서브 세트를 삭제하는 것이 유효합니다. 필터에 포함 된 항목 만 영향을받습니다.

  • 패치도 유효합니다. 이론적으로는 "작업"목록을 제공해야합니다. 예를 들어, 기술적으로 다음과 같은 것을 보내야합니다.

    [{ 
        "action": "update",
        "id": <id>,
        "value": {...}
    },{
        "action": "add",
        "value": {...}
    }, ...]
    

    실제로, 각 항목이 UPSERT (업데이트 또는 삽입) 논리를 사용하여 처리되는 일부 오브젝트 목록을 허용하는 API를 보는 것이 더 일반적입니다.

  • 기술적으로 POST는 "자원 자체의 고유 의미에 따라"입력을 처리해야합니다.

    • 실제로 POST는 일반적으로 "만들기"작업에 사용됩니다.
    • 그러나 POST는 비표준 호출에 사용되는 동사이기도합니다. 조치 엔드 포인트가 엄격하게 RESTful인지 ( "아니오"와 함께) 여부에 대한 격렬한 논쟁이 있지만 POST와 같은 엔드 포인트에 요청을 제출하는 경우 POST는 적절한 동사 {resource}/activate입니다.

참고 : 컬렉션에서 비 GET 작업을 사용하는 경우 성공 및 실패 정의를 신중하게 고려하십시오. REST는 부분적인 성공을 알리는 좋은 방법을 제공하지 않습니다. 기본적으로는 성공 기준이 모두없는 트랜잭션에서 작업을 실행한다고 가정하는 것이 좋습니다. 이것이 원하는 것이 아니라면 컬렉션과 직접 상호 작용하지 않아야합니다.

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