Bir istekte birden çok öğe oluşturmanın RESTful yolu


122

Siparişleri toplamak için küçük bir istemci sunucu programı üzerinde çalışıyorum. Bunu "DİNLENME (tam) bir şekilde" yapmak istiyorum.

Yapmak istediğim şey:

Tüm sipariş satırlarını (ürün ve miktar) toplayın ve siparişin tamamını sunucuya gönderin

Şu anda bunu yapmak için iki seçenek görüyorum:

  1. Her sipariş hattını sunucuya gönderin: POST miktarı ve ürün_kimliği

Aslında bunu yapmak istemiyorum çünkü istek sayısını sunucuya sınırlamak istiyorum, bu nedenle seçenek 2:

  1. Tüm sipariş sıralarını toplayın ve bir kerede sunucuya gönderin.

2. seçeneği nasıl uygulamalıyım? birkaç fikrim var: Tüm sipariş satırlarını bir JSON nesnesine sarın ve bunu sunucuya gönderin veya sipariş satırlarını göndermek için bir dizi kullanın.

2. seçeneği uygulamak iyi bir fikir mi yoksa iyi bir uygulama mı ve eğer öyleyse bunu nasıl yapmalıyım?

İyi uygulama nedir?

rest  post 

Yanıtlar:


74

Buna yaklaşmanın başka bir doğru yolunun, kaynak koleksiyonunuzu temsil eden başka bir kaynak yaratmak olacağına inanıyorum. Örneğin, benzer bir uç /api/sheep/{id}noktamız olduğunu /api/sheepve koyun kaynağı oluşturmak için POST yapabileceğimizi hayal edin .

Şimdi, toplu oluşturmayı desteklemek istiyorsak, adresinde yeni bir sürü kaynağı düşünmeliyiz /api/flock(veya /api/<your-resource>-collectiondaha iyi anlamlı bir adınız yoksa). Kaynakların veritabanınız veya uygulama modellerinizle eşlenmesine gerek olmadığını unutmayın . Bu yaygın bir yanılgıdır.

Kaynaklar, verilerinizle ilgisi olmayan daha yüksek seviyeli bir temsildir. Bir kaynak üzerinde çalışmak, bir kullanıcıya uyarı vermek, diğer ilgili verileri güncellemek, uzun ömürlü bir süreci başlatmak gibi önemli yan etkilere sahip olabilir. Örneğin, bir dosya sistemini veya hatta psbir REST API olarak unix komutunu eşleyebiliriz .

Bir kaynağı çalıştırmanın bir yan etki olarak başka birkaç varlık yaratmak anlamına da gelebileceğini varsaymanın güvenli olduğunu düşünüyorum.


Ben buna katılıyorum. Kaynağınızın bir koleksiyonu kavramını soyutlamalı ve buna bir kaynak gibi davranmalısınız. Bu,
bununla

Bu doğru yaklaşımdır. Bu POST Toplama isteğini bozmaz. O zamandan beri, tek bir varlığı göndermek için kullanılır. "Ayrı bir toplu varlık" ile toplu istek göndermek doğru yaklaşımdır.
Sorter

2
Api uç noktasının koyun ve sürü ile isimlendirilmesini çok seviyorum! Bir dereceye kadar soyutlamayla neredeyse Kutsal Kitap'a ait bir referansı var: "Bu kattan olmayan başka koyunlarım var; onları da getirmeliyim ve sesimi duyacaklar; ve bir çobanla tek sürü olacaklar." Yuhanna 10:16.
Evgeny

1
İlginç bir şekilde, insanlar tek bir kaynak oluşturmak istediğinizde URL'deki çoğul biçimi (koleksiyonun) kullanmanızı tavsiye eder, örneğin: bir kitap oluşturmak için / api / books'a bir POST gönderin. Ancak 100 kitap oluşturmak istediğinizde (json olarak tek bir istekte), 100 kitap koleksiyonunu hangi URL’ye gönderirsiniz? huzursuzluk burada başlar.
code4kix

@ Kullanabileceğin code4kix /api/book-group, /api/book-collectionveya buna benzer.
miguelcobain

46

Toplu işlemler (örn. Toplu oluşturma) birçok sistemde gerekli olmasına rağmen, bunlar resmi olarak RESTful mimari tarzı tarafından ele alınmaz.

Önerdiğiniz gibi bir koleksiyonu POST yapmanın temelde işe yaradığını, ancak böyle bir isteğe yanıt olarak hataları bildirmeniz gerektiğinde sorunlar ortaya çıktığını fark ettim. Bu tür sorunlar, farklı nedenlerden dolayı birden fazla arıza meydana geldiğinde veya sunucu işlemleri desteklemediğinde daha kötüdür. Size tavsiyem, performans sorunu yoksa, örneğin servis sağlayıcı LAN üzerindeyse (WAN değil) veya veriler nispeten küçükse, sunucuya 100 POST isteği göndermeye değer. Basit tutun, ayrı isteklerle başlayın ve bir performans sorununuz varsa optimize etmeye çalışın.


3
Gruplama durumundaki hatalar için kendiniz bir çözüm buldunuz mu? Bir mobil bağlantıda, bir sayfanın kötü bir fikir gibi görünmesini sağlamak için 100 gönderi isteği göndermek.
Thomas Ahle

Hataları bir diziye eklerim, kullanıcıyı bir 419 Çakışma hata sayfasına yönlendiririm (ve bu hatayı istemciye gönderirim) ve hatalar dizisini görüntülerim. Daha fazla ayrıntı için aşağıdaki cevabıma bakın.
Eric Fuller

5
Bu saçmalık. Soru, birçok öğe için bir sipariş göndermeyle ilgilidir, pek çoğunun söylediği gibi, yalnızca bir POST isteğinin varlığında yapabilirsiniz. Sunucunun bunu nasıl ele aldığı tamamen başka bir şeydir. Bu durumda, bir sipariş oluşturmada, bu sipariş için yapabileceklerinizi doldurmada ve ayrıca gerçekleştirilemeyen ayrıntıları doldurmada herhangi bir sorun görmüyorum. Bu şekilde, bir kullanıcı siparişlerini görebilir ve siparişe N öğe hariç tümünün eklendiğini, ancak bazılarının stokta kalmadığını veya sistemin ne yapacağını bilmediğini görebilir. Daha basit ancak daha az kullanıcı dostu bir seçenek de her şeyi reddetmektir
thecoshman

2
@thecoshman 3.25 yılda çok değişiyor. Muhtemelen soruya tamamen formüle edilmiş bir cevap vermelisiniz.
dlamblin

3
@dlamblin evet, muhtemelen bir çok şey yapmalıyım ... Bir aşamada bunu
başarabilirim

9

Facebook bunun nasıl yapılacağını açıklıyor: https://developers.facebook.com/docs/graph-api/making-multiple-requests

Basit toplu istekler

Toplu API, JSON dizileri olarak temsil edilen bir dizi mantıksal HTTP isteklerini alır - her isteğin bir yöntemi (GET / PUT / POST / DELETE vb. HTTP yöntemine karşılık gelir), bir göreli_url (URL'nin grafiğinden sonraki kısmı. com), isteğe bağlı üstbilgi dizisi (HTTP üstbilgilerine karşılık gelir) ve isteğe bağlı bir gövde (POST ve PUT istekleri için). Batch API, JSON dizileri olarak temsil edilen bir mantıksal HTTP yanıtları dizisi döndürür - her yanıtın bir durum kodu, isteğe bağlı bir üstbilgi dizisi ve isteğe bağlı bir gövdesi (JSON kodlu bir dizedir) vardır.


1
Bu çok ilginç bir bağlantı, önerilen çözüm bana kullanışlı geliyor. Her neyse, StackOverflow'da tercih edilen yanıt, bağlantılar değişebileceği veya kaybolabileceği için bir yanıtın gövdesinde çözüm kavramını açıklamaktır.
Jan Vlcinsky

7
Bu gerçekten Facebook'un bunu yapma şekli, OP'nin sorduğu gibi mutlaka RESTful değil
0cd

Sanırım bir Batch API (Google, Facebook, vb. - @PuneetArora'dan) birkaç alakasız isteği bir arada gruplandırırken daha kullanışlı. Tek bir öğe oluşturan bir istek oluşturmak ve ardından tüm bu istekleri bir dizi öğe göndermek için gruplamak "çılgınlıktır" (Einstein). Bir öğe koleksiyonunu geçen bir istek oluşturmanız yeterlidir.
tfmontague

8

Fikriniz benim için geçerli görünüyor. Uygulama tercihinize bağlıdır. Bunun için JSON kullanabilir veya sadece parametreleri ("order_lines []" dizisi) kullanabilir ve

POST /orders

Tek bir eylemde (sıra ve satırları) aynı anda daha fazla kaynak yaratacağınız için, bunların her birini doğrulamak ve yalnızca tümü doğrulamadan geçerse kaydetmek çok önemlidir. bunu bir işlemde yapmalısın.



5

Aslında son zamanlarda bununla boğuşuyorum ve işte bunun için çalışıyorum.

Birden fazla kaynak ekleyen bir POST başarılı olursa, okundu olarak eklenen tüm kaynakları görüntüleyen bir sayfayla birlikte 200 OK (bir 201'i düşünüyordum, ancak kullanıcı nihayetinde oluşturulan bir kaynağa inmiyor) döndürün -yalnızca veya düzenlenebilir moda. Örneğin, bir kullanıcı, yalnızca tek bir dosya girişi içeren bir formu kullanarak birden fazla görüntüyü seçebilir ve bir galeriye POST edebilir. POST isteği bütünüyle başarılı olursa, kullanıcıya, oluşturulan her görüntü kaynağı temsili için, her biri hakkında daha fazla ayrıntı (ad, açıklama, vb.) Belirtmelerine olanak tanıyan bir dizi form sunulur.

Bir veya daha fazla kaynağın yaratılamaması durumunda, POST işleyicisi tüm işlemleri durdurur ve her bir hata mesajını bir diziye ekler. Ardından, bir 419 Çakışması döndürülür ve kullanıcı, hata dizisinin içeriğini ve ayrıca gönderilen forma geri dönüş yolunu gösteren bir 419 Çakışma hata sayfasına yönlendirilir.


-2

100 sipariş satırı için HTTP başlıklarını göndermek istemezsiniz. Gerekenden daha fazla istek oluşturmak istemezsiniz.

Tüm siparişi bir JSON nesnesi içinde sunucuya gönder: sunucu / sipariş veya sunucu / sipariş / yeni. Şunu gösteren bir şey döndür: server / order / order_id

Ayrıca POST yerine CREATE PUT kullanmayı düşünün


Sanırım HTTP POST yönteminden bahsetti. CREATE HTTP yöntemi diye bir şey yoktur.
Milan Novota

Yok mu Oh bekle, yoktu. Bunun yerine PUT vardı.
Neşeli

22
Neden içerik oluşturmak için PUT kullanırsınız? HTTP POST yöntemi tam olarak bunun içindir.
thecoshman

8
İstemcinin webdav'da olduğu gibi kaynağın URI'sini belirtmesini istediğinizde kaynakları oluşturmak için PUT kullanırsınız. Posterin PUT kullanımına katılmıyorum, ancak kaynak yaratmada bir yeri var, ancak bu yer kapsam olarak sınırlı olabilir.
user602525

2
Not: Bir varlığın POSTlanması, varlığın talepte ele alınan kaynağın bir alt birimi haline gelmesi ile sonuçlanmalıdır ve idempotent değildir. PUT, adresteki varlığın yerini alır ve idempotenttir. İdeopotens (kelime?) Tüketiciler için önemli bir beklentidir.
Luke Puplett
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.