Apakah boleh mengubah sebagian koleksi dengan PUT atau DELETE?

21

Saya memiliki koleksi produk dalam grup produk, misalnya:

product-groups/123/products
  1. Jika saya perlu menambah koleksi, apakah boleh saya hanya melewati beberapa produk dengan PUT?

  2. Jika saya perlu menghapus beberapa produk dari koleksi, apakah boleh saya melewati data filter (array ID) dengan DELETE?

Apa cara terbaik untuk mengimplementasikan fungsionalitas dalam semangat ReST?

Sunting: item adalah tautan ke entitas yang terpisah, pada dasarnya ID produk.

pengguna151851
sumber
Apakah item dalam kelompok produk sumber daya yang terpisah dikelola di tempat lain? Atau apakah mereka hanya bagian dari koleksi grup produk? Jika terpisah, dapatkah produk termasuk dalam beberapa kelompok produk?
Martijn Pieters
2
mungkin PATCH Spesifikasi ini menentukan metode HTTP / 1.1 [RFC2616] yang baru, PATCH, yang digunakan untuk menerapkan modifikasi parsial ke sumber daya.
Esailija
Suatu produk (ID) dapat dimiliki oleh beberapa kelompok produk.
user151851
Apakah ada cara yang terkenal (praktik terbaik) untuk mengatakan bagaimana cara PATCH yaitu menambah atau menghapus produk dalam koleksi?
user151851
Pertanyaan serupa pada SO stackoverflow.com/questions/411462/...
Luke Puplett

Jawaban:

10

Secara umum, Anda memiliki satu titik akhir yang mewakili seluruh koleksi x :

/products

Katakanlah, Anda ingin memperbarui satu produk, Anda membuat PUT ke /products/{id}. Jika Anda ingin memperbarui sebagian produk tunggal (tidak memperbarui setiap bidang), Anda juga dapat menggunakan PATCH untuk /products/{id}. Hal yang sama berlaku untuk penghapusan satu entitas ( HAPUS ke /products/{id}).

Jika Anda ingin menargetkan sumber daya tunggal , Anda memenuhi syarat melalui jalur, sumber daya tunggal mana, yang ingin Anda modifikasi.

Satu-satunya tindakan yang memecah skema adalah penciptaan sumber daya. Saat membuat sumber daya Anda menargetkan koleksi secara keseluruhan, katakan POST ke /products.

Karena itu, harus jelas, bahwa target untuk operasi yang mempengaruhi pengumpulan secara keseluruhan, harus pergi ke pengumpulan-endpoint yang sesuai.

Misalnya Anda ingin mengambil subset dari produk yang berwarna merah, Anda memintanya

GET untuk /products?colour=red.

Jadi, jika Anda ingin menghapus semua ini, Anda HAPUS /products?colour=red . Atau jika Anda ingin menghapus beberapa produk melalui id, Anda bisa HAPUS /products?id=1&id=2&id=3 .

Bagaimana dengan pembuatan sumber daya massal ? POST koleksi Anda [{...},{...},{...}]hanya untuk /products. Hal yang sama berlaku untuk PUT dan PATCH .

Itu sangat mudah.

Untuk menjawab pertanyaan Anda:

Jika saya perlu menambah koleksi, apakah boleh saya melewati beberapa produk dengan PUT?

Tidak hanya OK, Anda didorong untuk melakukannya seperti itu.

Jika saya perlu menghapus beberapa produk dari koleksi, apakah boleh saya melewati data filter (array ID) dengan DELETE?

Tidak apa-apa. Seperti yang dituliskan oleh Eneko Alonso, kadang-kadang ada operasi massal yang dienkapsulasi melalui "controller" -poin, yaitu POST digunakan untuk memicu operasi (kompleks).

Thomas Junk
sumber
2
PUT adalah mengganti operasi. Memanggil PUT pada titik akhir pengumpulan dengan "beberapa produk" harus menghapus (dalam kasus OP, menghapus hubungan dengan) produk apa pun yang tidak termasuk dalam daftar "beberapa produk". Meskipun dapat digunakan untuk menambah item, itu juga harus menghapus item yang tidak (menurut saya) seperti yang diharapkan OP. Anda harus merevisi tanggapan Anda untuk pertanyaan pertama mereka sesuai.
claytond
@ claytond: Saya kira jawabannya baik-baik saja, selama sebagian pembaruan dilakukan PATCH, dan penggantian lengkap, melalui PUT.
9000
4
@ 9000. Tentu saja, tetapi jawabannya saat ini mengatakan "Anda didorong untuk ... menambah koleksi ... hanya dengan beberapa produk dengan PUT". Itu tentu saja salah. Didorong ke POST. Mampu PUT ... tetapi hanya dengan melewati semua (tidak beberapa) item.
claytond
5

Biasanya, metode REST dimaksudkan untuk beroperasi pada satu entitas / objek (CRUD).

Ada beberapa opsi:

  • Perlakukan koleksi Anda sebagai entitas dan perbarui melalui POST
  • Buat operasi alternatif, non-REST

Yang pertama mengikuti standar REST, tetapi bisa mahal, karena objek koleksi Anda / entitas mungkin sangat besar (memperbarui grup yang memiliki ribuan produk hanya untuk menambah / menghapus satu produk akan menjadi permintaan berat).

Opsi kedua lebih disukai oleh banyak API, sebagai cara untuk memperpanjang REST di luar operasi CRUD.

Sebagai contoh:

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)

Banyak API selalu menggunakan POST untuk operasi yang diperluas ini, tetapi tidak ada yang membatasi Anda untuk menggunakan metode http lainnya (selain dari batasan GET dan DELETE untuk memiliki badan kosong)

Eneko Alonso
sumber
Tentu, ada beberapa metode untuk melakukan mencapai tujuan. Yang satu adalah praktek terbaik? Mana yang akan lebih masa depan-bukti?
user151851
4
@ user151851: Kepatuhan total REST (jika ada hal seperti itu) adalah tujuan yang tinggi. Garis besar pendekatan di sini tampaknya lebih realistis, karena upaya ini menggunakan pendekatan yang sebenarnya digunakan di "dunia nyata," menjadikannya, pada dasarnya, standar de facto. Itu tentang bukti masa depan yang akan Anda dapatkan.
Robert Harvey
2
Bukankah kita memperkenalkan kata kerja khusus menggunakan "append" dan "delete" di URL? Dengan cara itu kita harus menjelaskan bagaimana menggunakan API. Bukankah kita harus menggunakan kembali apa yang kita miliki yaitu metode HTTP? Dalam hal ini tindakannya sudah dikenal luas.
user151851
7
Untuk siapa pun yang kebetulan menjawab ini: Itu salah. Seperti @ user151851 sebutkan, ini memperkenalkan kata kerja ke dalam URL yang kira-kira non-RESTful yang bisa Anda dapatkan. Sehubungan dengan pertanyaan yang sebenarnya, saya tidak punya jawaban yang bagus, tapi yang ini bukan.
umbrae
Mungkinkah "ekstensi" lebih berorientasi pada sumber daya dengan membuatnya products/collectionyang mengembalikan 'amplop' item dan konten amplop diubah melalui PUT? Seperti, "inilah tepatnya yang saya inginkan dari item dalam koleksi".
Luke Puplett
3

Hanya untuk menjawab jawaban / komentar sebelumnya.

Sesuai pengetahuan saya, POST adalah metode untuk menambahkan elemen tunggal ke koleksi.

DELETE pada gilirannya, adalah metode untuk menghapus elemen tunggal dari koleksi. Kedua skenario itu benar-benar tenang.

Namun, Anda harus menggunakan URI yang sesuai untuk merujuk elemen tunggal atau seluruh koleksi.

Misalnya, untuk menambahkan elemen ke koleksi Anda harus POST data ke URI berikut:

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

Untuk menghapus satu produk dari koleksi, Anda dapat menggunakan metode DELETE mengirim permintaan ke sesuatu seperti:

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

Metode PATCH dapat digunakan untuk memperbarui beberapa elemen dalam koleksi. Misalnya, ketika Anda hanya perlu memperbarui satu bidang dalam satu elemen. MENEMPATKAN representasi sumber daya lengkap untuk koleksi yang sangat besar dapat menjadi operasi yang sangat mahal.

Lukasz
sumber
2

Pada prinsipnya, semua operasi RESTful berlaku pada koleksi, tetapi pastikan Anda memahami bagaimana semantik kata kerja berlaku untuk koleksi:

  • PUT adalah pengganti yang lengkap .

    • Jika Anda PUT ke tunggal (misalnya /item/{id}) dan meninggalkan namekeluar, itu harus dibersihkan atau diatur ke nol atau sesuatu yang serupa.
    • Jika Anda PUT untuk koleksi dan tidak termasuk item, itu harus dihapus dari koleksi itu.

    Sementara PUT dapat digunakan untuk menambahkan item, Anda harus mengirim "semua" item. Mengirim "beberapa" item harus menghasilkan kepindahan (saya menganggap ini adalah bukan apa keinginan OP).

  • HAPUS lebih intuitif. Adalah sah untuk menghapus koleksi atau bagian yang difilter daripadanya. Hanya item yang termasuk dalam filter yang akan terpengaruh.

  • PATCH juga valid. Secara teori, Anda seharusnya memberikan daftar "operasi". Misalnya, Anda harus mengirim sesuatu seperti:

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

    Dalam praktiknya, lebih umum untuk melihat API yang menerima sebagian daftar objek tempat setiap item diproses menggunakan logika UPSERT (perbarui atau masukkan).

  • Secara teknis, POST harus memproses input "sesuai dengan semantik spesifik sumber daya itu sendiri".

    • Dalam praktiknya, POST biasanya digunakan untuk operasi "buat".
    • Namun, POST juga kata kerja yang digunakan untuk panggilan non-standar. Meskipun ada perdebatan yang sengit apakah titik akhir tindakan benar-benar Tenang (saya berpihak pada "tidak"), POST adalah kata kerja yang tepat jika Anda mengirimkan permintaan ke titik akhir seperti {resource}/activate.

CATATAN: Saat menggunakan operasi non-GET pada koleksi, pertimbangkan dengan hati-hati definisi keberhasilan dan kegagalan. REST tidak memberi Anda cara yang baik untuk mengomunikasikan keberhasilan parsial. Default yang baik adalah dengan menganggap bahwa Anda akan menjalankan operasi dalam transaksi dengan kriteria keberhasilan semua atau tidak sama sekali. Jika ini bukan yang Anda inginkan, Anda mungkin tidak boleh berinteraksi dengan koleksi secara langsung.

claytond
sumber