Cara tenang untuk membuat banyak item dalam satu permintaan

122

Saya sedang mengerjakan program server klien kecil untuk mengumpulkan pesanan. Saya ingin melakukan ini dengan "REST (ful) way".

Yang ingin saya lakukan adalah:

Kumpulkan semua orderlines (produk dan kuantitas) dan kirim pesanan lengkap ke server

Saat ini saya melihat dua opsi untuk melakukan ini:

  1. Kirim setiap baris pesanan ke server: POST qty dan product_id

Saya sebenarnya tidak ingin melakukan ini karena saya ingin membatasi jumlah permintaan ke server jadi opsi 2:

  1. Kumpulkan semua orderlines dan kirimkan ke server sekaligus.

Bagaimana cara menerapkan opsi 2? beberapa ide yang saya miliki adalah: Bungkus semua orderlines dalam objek JSON dan kirim ini ke server atau gunakan array untuk memposting orderlines.

Apakah itu ide yang baik atau praktik yang baik untuk menerapkan opsi 2, dan jika demikian, bagaimana saya harus melakukannya.

Apa praktik yang baik?


sumber

Jawaban:

74

Saya yakin bahwa cara lain yang benar untuk melakukan pendekatan ini adalah dengan membuat sumber daya lain yang mewakili koleksi sumber daya Anda. Contoh, bayangkan bahwa kita memiliki endpoint seperti /api/sheep/{id}dan kita dapat melakukan POST /api/sheepuntuk membuat resource domba.

Sekarang, jika kita ingin mendukung pembuatan massal, kita harus mempertimbangkan sumber daya flock baru di /api/flock(atau /api/<your-resource>-collectionjika Anda tidak memiliki nama yang bermakna lebih baik). Ingatlah bahwa sumber daya tidak perlu dipetakan ke database atau model aplikasi Anda . Ini adalah kesalahpahaman yang umum.

Sumber daya adalah representasi tingkat yang lebih tinggi, tidak terkait dengan data Anda. Mengoperasikan sumber daya dapat memiliki efek samping yang signifikan, seperti mengaktifkan peringatan kepada pengguna, memperbarui data terkait lainnya, memulai proses yang berumur panjang, dll. Misalnya, kita dapat memetakan sistem file atau bahkan psperintah unix sebagai REST API.

Saya pikir aman untuk mengasumsikan bahwa mengoperasikan sumber daya juga dapat berarti membuat beberapa entitas lain sebagai efek samping.

miguelcobain.dll
sumber
Saya setuju dengan ini. Anda harus mengabstraksi konsep kumpulan sumber daya Anda dan memperlakukannya seperti sumber daya. Ini akan memberi Anda lebih banyak fleksibilitas di masa depan juga, ketika Anda ingin mulai melakukan operasi pada ini, dll.
villy393
Ini adalah pendekatan yang tepat. Ini tidak merusak permintaan Koleksi POS. Karena, digunakan untuk memposting satu entitas. Mengirim permintaan massal dengan "entitas massal terpisah" adalah pendekatan yang tepat.
Penyortir
2
Saya suka Anda penamaan titik akhir api dengan domba dan kawanan domba! Dengan tingkat abstraksi hampir memiliki referensi alkitabiah: "Aku punya domba lain, yang bukan dari kandang ini; Aku harus membawa mereka juga, dan mereka akan mendengar suara-Ku; dan mereka akan menjadi satu kawanan dengan satu gembala." Yohanes 10:16.
Evgeny
1
Menariknya, orang merekomendasikan penggunaan bentuk jamak (dari koleksi) di URL saat Anda ingin membuat sumber daya tunggal, seperti: kirim POST ke / api / books untuk membuat buku. Tetapi kemudian ketika Anda ingin membuat 100 buku (dalam satu permintaan sebagai json), ke URL mana Anda akan memposting koleksi 100 buku? di situlah kegelisahan dimulai.
code4kix
@ code4kix yang dapat Anda gunakan /api/book-group, /api/book-collectionatau yang serupa.
miguelcobain
46

Meskipun operasi massal (misalnya pembuatan batch) sangat penting dalam banyak sistem, operasi tersebut tidak secara formal ditangani oleh gaya arsitektur RESTful.

Saya menemukan bahwa POST koleksi seperti yang Anda sarankan pada dasarnya berfungsi, tetapi masalah muncul saat Anda perlu melaporkan kegagalan sebagai tanggapan atas permintaan semacam itu. Masalah seperti itu menjadi lebih buruk ketika beberapa kegagalan terjadi karena penyebab yang berbeda atau ketika server tidak mendukung transaksi. Saran saya untuk Anda adalah jika tidak ada masalah kinerja, misalnya ketika penyedia layanan di LAN (bukan WAN) atau datanya relatif kecil, ada baiknya untuk mengirim 100 permintaan POST ke server. Sederhanakan, mulailah dengan permintaan terpisah dan jika Anda mengalami masalah kinerja, coba optimalkan.

LiorH
sumber
3
Apakah Anda menemukan solusi sendiri untuk kesalahan dalam kasus pengelompokan? Pada koneksi seluler mengirim 100 permintaan posting untuk menunjukkan jahitan halaman seperti ide yang buruk.
Thomas Ahle
Saya menambahkan error ke array, mengarahkan pengguna ke halaman error 419 Conflict (dan mengembalikan error tersebut ke klien), dan menampilkan array error. Lihat jawaban saya di bawah untuk lebih jelasnya.
Eric Fuller
5
Ini tidak masuk akal. Pertanyaannya adalah tentang mengirim pesanan untuk banyak item, yang seperti yang dikatakan banyak orang, Anda hanya dapat berada di entitas satu permintaan POST. Bagaimana server menangani itu adalah hal yang sama sekali berbeda. Dalam hal ini, saya melihat tidak ada masalah dengan membuat pesanan, mengisi apa yang Anda bisa untuk pesanan itu, dan juga mengisi detail yang tidak dapat dilakukan. Dengan begitu, pengguna kemudian dapat melihat pesanan mereka, dan melihat bahwa semua kecuali N item telah ditambahkan ke pesanan, tetapi beberapa sudah habis, atau sistem tidak tahu apa yang harus dilakukan. Opsi lain yang lebih sederhana namun kurang ramah pengguna adalah menolak semuanya
thecoshman
2
@thecoshman banyak berubah dalam 3,25 tahun. Anda mungkin harus memposting jawaban yang dirumuskan lengkap untuk pertanyaan tersebut.
dlamblin
3
@dlamblin ya, saya mungkin harus melakukan banyak hal ... Saya akan melakukannya pada tahap tertentu mungkin ...
thecoshman
9

Facebook menjelaskan bagaimana melakukan ini: https://developers.facebook.com/docs/graph-api/making-multiple-requests

Permintaan batch sederhana

Batch API mengambil array permintaan HTTP logis yang direpresentasikan sebagai array JSON - setiap permintaan memiliki metode (sesuai dengan metode HTTP GET / PUT / POST / DELETE dll.), Relative_url (bagian dari URL setelah graph.facebook. com), array header opsional (sesuai dengan header HTTP) dan badan opsional (untuk permintaan POST dan PUT). Batch API mengembalikan larik respons HTTP logis yang direpresentasikan sebagai larik JSON - setiap respons memiliki kode status, larik header opsional, dan isi opsional (yang merupakan string berenkode JSON).

rwitzel
sumber
1
Ini adalah tautan yang sangat menarik, solusi yang diusulkan tampaknya dapat digunakan oleh saya. Bagaimanapun, di StackOverflow, jawaban yang lebih disukai adalah menjelaskan konsep solusi dalam isi jawaban karena tautan dapat berubah atau menghilang.
Jan Vlcinsky
7
Itu benar-benar cara Facebook melakukannya, belum tentu RESTful seperti yang diminta OP
0cd
Saya pikir Batch API (dari Google, Facebook, dll - @PuneetArora) lebih berguna saat mengelompokkan beberapa permintaan yang tidak terkait menjadi satu. Membuat permintaan yang membuat satu item, dan kemudian mengelompokkan semua permintaan itu bersama-sama untuk mengirim koleksi item adalah "kegilaan" (Einstein). Buat saja permintaan yang melewati koleksi item.
tfmontague
8

Ide Anda tampaknya valid bagi saya. Penerapannya tergantung pada preferensi Anda. Anda dapat menggunakan JSON atau hanya parameter untuk ini (array "order_lines []") dan lakukan

POST /orders

Karena Anda akan membuat lebih banyak sumber daya sekaligus dalam satu tindakan (urutan dan barisnya), penting untuk memvalidasi masing-masing dan semuanya dan menyimpannya hanya jika semuanya lulus validasi, yaitu. Anda harus melakukannya dalam transaksi.

Milan Novota
sumber
6

Saya kira lebih baik mengirim permintaan terpisah dalam satu koneksi . Tentu saja, server web Anda harus mendukungnya

zakovyrya.dll
sumber
5

Saya sebenarnya bergulat dengan ini akhir-akhir ini, dan inilah yang sedang saya upayakan.

Jika POST yang menambahkan banyak sumber daya berhasil, kembalikan 200 OK (saya mempertimbangkan 201, tetapi pengguna pada akhirnya tidak mendarat di sumber daya yang dibuat) bersama dengan halaman yang menampilkan semua sumber daya yang ditambahkan, baik dalam membaca mode -hanya atau diedit. Misalnya, pengguna dapat memilih dan POST beberapa gambar ke galeri menggunakan formulir yang hanya terdiri dari satu input file. Jika permintaan POST berhasil secara keseluruhan, pengguna disajikan dengan satu set formulir untuk setiap representasi sumber gambar yang dibuat yang memungkinkan mereka untuk menentukan detail lebih lanjut tentang masing-masing (nama, deskripsi, dll).

Jika satu atau lebih sumber daya gagal dibuat, penangan POST membatalkan semua pemrosesan dan menambahkan setiap pesan kesalahan individu ke larik. Kemudian, 419 Konflik dikembalikan dan pengguna diarahkan ke halaman kesalahan 419 Konflik yang menyajikan konten dari array kesalahan, serta cara kembali ke formulir yang telah dikirimkan.

Eric Fuller
sumber
-2

Anda tidak ingin mengirim header HTTP untuk 100 baris pemesanan. Anda tidak ingin membuat permintaan lebih dari yang diperlukan.

Kirim seluruh pesanan dalam satu objek JSON ke server, ke: server / order atau server / order / baru. Kembalikan sesuatu yang mengarah ke: server / order / order_id

Pertimbangkan juga untuk menggunakan CREATE PUT daripada POST

Riang
sumber
Saya kira dia menggunakan metode HTTP POST. Tidak ada yang namanya metode CREATE HTTP.
Milan Novota
Apakah tidak ada? Oh tunggu, tidak ada. Ada PUT sebagai gantinya.
Ceria
22
Mengapa Anda menggunakan PUT untuk membuat konten? Untuk itulah tepatnya metode HTTP POST.
thecoshman
8
Anda menggunakan PUT untuk membuat sumber daya saat Anda ingin klien menentukan URI sumber daya, seperti di webdav. Saya tidak setuju dengan penggunaan PUT oleh poster, tetapi PUT memiliki tempat dalam menciptakan sumber daya, meskipun tempat itu mungkin terbatas cakupannya.
pengguna602525
2
Catatan: Melakukan POST entitas akan mengakibatkan entitas menjadi bawahan dari sumber daya yang disebutkan dalam permintaan dan tidak idempoten. PUT menggantikan entitas di alamat dan idempoten. Idempotensi (kata?) Merupakan harapan penting bagi konsumen.
Luke Puplett