Bạn có thể thay đổi một phần bộ sưu tập bằng PUT hoặc DELETE không?


21

Tôi có một bộ sưu tập các sản phẩm trong một nhóm sản phẩm, ví dụ:

product-groups/123/products
  1. Nếu tôi cần thêm vào bộ sưu tập, tôi có thể chỉ chuyển một số sản phẩm với PUT không?

  2. Nếu tôi cần xóa một số sản phẩm khỏi bộ sưu tập, tôi có thể chuyển dữ liệu bộ lọc (một mảng ID) bằng DELETE không?

Cách tốt nhất để thực hiện các chức năng theo tinh thần của ReST là gì?

Chỉnh sửa: các mục là các liên kết đến các thực thể riêng biệt, về cơ bản là ID của sản phẩm.


Là các mục trong nhóm sản phẩm tài nguyên riêng biệt được quản lý ở nơi khác? Hay chúng chỉ là một phần của bộ sưu tập nhóm sản phẩm? Nếu riêng biệt, sản phẩm có thể thuộc nhiều nhóm sản phẩm?
Martijn Pieters

2
có lẽ PATCH Đặc điểm kỹ thuật này xác định phương thức HTTP / 1.1 [RFC2616] mới, PATCH, được sử dụng để áp dụng sửa đổi một phần cho tài nguyên.
Esailija

Một sản phẩm (ID) có thể thuộc về một số nhóm sản phẩm.
dùng151851

Có một cách nổi tiếng (thực hành tốt nhất) để nói làm thế nào để BẮT ĐẦU tức là thêm hoặc xóa sản phẩm trong bộ sưu tập?
dùng151851

Câu hỏi tương tự trên SO stackoverflow.com/questions/411462/
Mạnh

Câu trả lời:


10

Nói chung, bạn có một điểm cuối đại diện cho toàn bộ bộ sưu tập của x :

/products

Này, bạn muốn cập nhật một sản phẩm duy nhất, bạn thực hiện một PUT để /products/{id}. Nếu bạn muốn cập nhật một phần một sản phẩm (không cập nhật mọi lĩnh vực), bạn cũng có thể sử dụng một BƯỚC để /products/{id}. Điều tương tự cũng xảy ra đối với việc xóa một thực thể duy nhất ( XÓA đến /products/{id}).

Nếu bạn muốn nhắm mục tiêu một nguồn tài nguyên duy nhất , bạn đủ điều kiện thông qua đường dẫn, đó là nguồn tài nguyên duy nhất , bạn muốn sửa đổi.

Hành động duy nhất phá vỡ sơ đồ là tạo ra một nguồn tài nguyên. Khi tạo một ressource bạn nhắm mục tiêu các bộ sưu tập như một toàn thể, nói POST để /products.

Điều đó nói rằng, cần phải rõ ràng, rằng mục tiêu cho các hoạt động ảnh hưởng đến toàn bộ bộ sưu tập, nên đi đến điểm cuối của bộ sưu tập thích hợp.

Ví dụ: bạn muốn truy xuất một tập hợp con các sản phẩm có màu đỏ, bạn yêu cầu nó bằng cách

GET để /products?colour=red.

Vì vậy, nếu bạn muốn xóa tất cả những thứ này, bạn XÓA /products?colour=red . Hoặc nếu bạn muốn xóa một số sản phẩm thông qua id, bạn có thể XÓA /products?id=1&id=2&id=3 .

Điều gì về việc tạo ra số lượng lớn các nguồn tài nguyên? POST bộ sưu tập của bạn [{...},{...},{...}]chỉ đơn giản là để /products. Điều tương tự cũng xảy ra với PUTPATCH .

Điều đó thực sự đơn giản.

Để trả lời câu hỏi của bạn:

Nếu tôi cần thêm vào bộ sưu tập, tôi có thể chỉ chuyển một số sản phẩm với PUT không?

Nó không chỉ OK, bạn được khuyến khích làm điều đó như thế.

Nếu tôi cần xóa một số sản phẩm khỏi bộ sưu tập, tôi có thể chuyển dữ liệu bộ lọc (một mảng ID) bằng DELETE không?

Vậy được rồi. Như Eneko Alonso đã viết, đôi khi có các hoạt động hàng loạt được gói gọn thông qua các điểm phụ "bộ điều khiển", tức là POST được sử dụng để kích hoạt các hoạt động (phức tạp).


2
PUT là một hoạt động thay thế. Gọi PUT trên điểm cuối của bộ sưu tập với "một số sản phẩm" sẽ xóa (trong trường hợp của OP, xóa mối quan hệ với) bất kỳ sản phẩm nào không có trong danh sách "một số sản phẩm". Mặc dù nó có thể được sử dụng để thêm các mục, nhưng nó cũng nên loại bỏ các mục không (theo ý kiến ​​của tôi) những gì OP mong đợi. Bạn nên xem lại câu trả lời của mình cho câu hỏi đầu tiên của họ.
claytond 22/03/18

@claytond: Tôi cho rằng câu trả lời là tốt, miễn là cập nhật một phần được thực hiện PATCHvà thay thế hoàn toàn, thông qua PUT.
9000

4
@ 9000. Tất nhiên, nhưng câu trả lời hiện tại cho biết "bạn được khuyến khích ... thêm vào bộ sưu tập ... [bằng cách] vượt qua [ing] chỉ một số sản phẩm có PUT". Điều đó chắc chắn không chính xác. Khuyến khích gửi. Có thể PUT ... nhưng chỉ bằng cách chuyển tất cả (không phải một số) vật phẩm.
claytond

5

Thông thường, các phương thức REST được dự định để hoạt động trên một thực thể / đối tượng (CRUD).

Có một số lựa chọn:

  • Hãy coi các bộ sưu tập của bạn là các thực thể và cập nhật chúng qua POST
  • Tạo các hoạt động thay thế, không phải REST

Cái đầu tiên tuân theo các tiêu chuẩn REST, nhưng có thể tốn kém, vì các đối tượng / thực thể bộ sưu tập của bạn có thể rất lớn (cập nhật một nhóm có hàng ngàn sản phẩm chỉ để thêm / xóa một sản phẩm sẽ là một yêu cầu nặng nề).

Tùy chọn thứ hai được nhiều API ưa thích, như một cách để mở rộng REST ngoài các hoạt động CRUD.

Ví dụ:

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)

Nhiều API sử dụng luôn POST cho các hoạt động mở rộng này, nhưng không có gì giới hạn bạn sử dụng các phương thức http khác (ngoài giới hạn NHẬN và XÓA để có phần thân trống)


Chắc chắn, có một vài phương pháp để đạt được mục tiêu. Cái nào là thực hành tốt nhất? Cái nào sẽ là bằng chứng trong tương lai?
dùng151851

4
@ user151851: Tổng tuân thủ REST (nếu có một điều như vậy) là một mục tiêu cao cả. Phác thảo phương pháp tiếp cận ở đây có vẻ thực tế hơn, vì nó cố gắng sử dụng một cách tiếp cận thực sự đang được sử dụng trong "thế giới thực", về bản chất, nó trở thành một tiêu chuẩn không chính xác. Đó là bằng chứng trong tương lai như bạn sẽ nhận được.
Robert Harvey

2
Chúng tôi không giới thiệu các động từ tùy chỉnh bằng cách sử dụng "chắp thêm" và "xóa" trong URL? Theo cách đó, chúng tôi sẽ phải giải thích cách sử dụng API. Chúng ta không nên sử dụng lại những gì chúng ta có, tức là các phương thức HTTP? Trong trường hợp các hành động được biết đến.
dùng151851

7
Đối với bất kỳ ai khác xảy ra với câu trả lời này: Đó là sai. Như @ user151851 đã đề cập, phần này giới thiệu các động từ vào URL không phải là RESTful như bạn có thể nhận được. Liên quan đến câu hỏi thực tế, tôi không có câu trả lời hay, nhưng đây không phải là câu trả lời.
cái rốn

"Phần mở rộng" có thể được định hướng tài nguyên hơn bằng cách làm cho nó products/collectiontrả về một 'phong bì' của các mục và nội dung phong bì được thay đổi thông qua PUT không? Giống như, "đây chính xác là cách tôi muốn các mục trong bộ sưu tập".
Luke Puplett

3

Chỉ cần trả lời / bình luận chính xác trước đó.

Theo hiểu biết của tôi, POST là phương pháp để thêm các yếu tố đơn lẻ vào bộ sưu tập.

Lần lượt XÓA, là phương pháp để xóa phần tử đơn khỏi bộ sưu tập. Cả hai kịch bản đều hoàn hảo RESTful.

Tuy nhiên, bạn nên sử dụng URI thích hợp để tham chiếu một phần tử hoặc toàn bộ bộ sưu tập.

Ví dụ: để thêm phần tử vào bộ sưu tập, bạn nên POST dữ liệu theo URI sau:

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

Để xóa một sản phẩm khỏi bộ sưu tập, bạn có thể sử dụng phương thức XÓA yêu cầu gửi đến một cái gì đó như:

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

Phương pháp PATCH có thể được sử dụng để cập nhật một số yếu tố trong bộ sưu tập. Chẳng hạn, khi bạn chỉ cần cập nhật một trường trong một phần tử. PUTting một đại diện tài nguyên hoàn chỉnh cho bộ sưu tập rất lớn có thể là hoạt động rất tốn kém.


2

Về nguyên tắc, tất cả các hoạt động RESTful đều hợp lệ trên một bộ sưu tập, nhưng hãy đảm bảo bạn hiểu cách thức ngữ nghĩa của các động từ áp dụng cho một bộ sưu tập:

  • PUT là một sự thay thế hoàn toàn .

    • Nếu bạn PUT cho một singleton (ví dụ /item/{id}) và bỏ nameđi, nó sẽ bị xóa hoặc được đặt thành null hoặc một cái gì đó tương tự.
    • Nếu bạn PUT vào một bộ sưu tập và không bao gồm một mục, thì nó sẽ bị xóa khỏi bộ sưu tập đó.

    Mặc dù PUT có thể được sử dụng để thêm các mục, bạn phải gửi "tất cả" các mục. Gửi "một số" mặt hàng sẽ dẫn đến việc xóa (tôi cho rằng đây không phải là điều OP mong muốn).

  • XÓA là trực quan hơn. Nó là hợp lệ để xóa bộ sưu tập hoặc bất kỳ tập hợp con được lọc của chúng. Chỉ các mục trong bộ lọc sẽ bị ảnh hưởng.

  • VĂN cũng có giá trị. Về lý thuyết, bạn phải cung cấp một danh sách "hoạt động". Ví dụ, về mặt kỹ thuật bạn nên gửi một cái gì đó như:

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

    Trong thực tế, thông thường hơn là thấy một API chấp nhận một danh sách một phần các đối tượng trong đó mỗi mục được xử lý bằng logic UPSERT (cập nhật hoặc chèn).

  • Về mặt kỹ thuật, POST nên xử lý đầu vào "theo ngữ nghĩa cụ thể của tài nguyên".

    • Trong thực tế, POST thường được sử dụng cho các hoạt động "tạo".
    • Tuy nhiên, POST cũng là động từ được sử dụng cho các cuộc gọi không chuẩn. Trong khi có tranh luận gay gắt về việc liệu các điểm cuối hành động có nghiêm túc RESTful (tôi bên cạnh "không"), POST là động từ thích hợp nếu bạn đang gửi yêu cầu đến điểm cuối như thế nào {resource}/activate.

LƯU Ý: Khi sử dụng các thao tác không NHẬN trên các bộ sưu tập, hãy xem xét cẩn thận định nghĩa về thành công và thất bại. REST không cung cấp cho bạn một cách tốt để giao tiếp thành công một phần. Một mặc định tốt là giả định rằng bạn sẽ chạy hoạt động trong một giao dịch với tiêu chí thành công hoàn toàn hoặc không có gì. Nếu đây không phải là điều bạn muốn, có lẽ bạn không nên tương tác trực tiếp với bộ sưu tập.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.