RESTful API'sinde komut desenini uygulama


12

Umarım olabildiğince RESTful hale getirmek için bir HTTP API tasarlama sürecindeyim.

İşlevselliğin birkaç kaynağa yayıldığı bazı eylemler vardır ve bazen geri alınması gerekir.

Kendi kendime düşündüm, bu bir komut kalıbına benziyor, ama onu bir kaynağa nasıl modelleyebilirim?

Böyle bir şeyle yaratılacak olan DepositAction gibi XXAction adında yeni bir kaynak tanıtacağım

POST /card/{card-id}/account/{account-id}/Deposit
AmountToDeposit=100, different parameters...

bu aslında yeni bir DepositAction oluşturur ve Do / Execute yöntemini etkinleştirir. Bu durumda, 201 Oluşturulan HTTP durumu döndürmek, işlemin başarıyla yürütüldüğü anlamına gelir.

Daha sonra bir müşteri eylem ayrıntılarına bakmak isterse

GET /action/{action-id}

Güncelleme / PUT bloke edilmelidir sanırım, çünkü burada alakalı değil.

Ve eylemi geri almak için kullanmayı düşündüm

DELETE /action/{action-id}

gerçekte ilgili nesnenin Geri Al yöntemini çağırır ve durumunu değiştirir.

Diyelim ki tek bir Do-Undo ile mutluyum, yeniden yapmam gerekmiyor.

Bu yaklaşım uygun mu?

Kullanılmaması gereken tuzaklar var mı?

Bu müşterilerin POV'sundan anlaşılıyor mu?


Kısa cevap, bu REST değil.
Evan Plaice

3
@EvanPlaice bunun üzerinde durmak ister misiniz? asıl soru bu.
Ocak'ta Mithir

1
Bir cevapta ayrıntıya girerdim ama Gary'nin yanıtı zaten eklediğim şeylerin çoğunu / hepsini kapsıyor. Dinlenmediğini söylüyorum çünkü URI'lerin sadece kaynakları temsil etmesi gerekiyordu (yani eylemleri değil). Eylemler GET / POST / PUT / DELETE / HEAD aracılığıyla gerçekleştirilir. REST'i bir OOP arayüzü olarak düşünün. Amaç, API'yi genel kalıba uydurmak ve onu uygulamaya özgü ayrıntılardan mümkün olduğunca ayırmaktır.
Evan Plaice

1
@EvanPlaice Tamam anlıyorum, teşekkürler. Sanırım burada kafa karıştırıcı çünkü Mevduat bir isim ve fiil olarak düşünülebilir ...
Mithir

Bu durumda URI, borçlanmanın (para çekme) ve kredilendirmenin (para verme) POST istekleri yoluyla yapılan işlemler olduğu bir işlemi temsil etmelidir. POST her ikisi için de kullanılır, çünkü paranın her iki yönde de hareket ettirilmesi, yeni bir işlemi oluşturduğunu gösterir. Özel durumunuzda, işlemler kart sahibinin hesabında gerçekleşir, böylece kartın hesap numarası kaynak URI'sı olur.
Evan Plaice

Yanıtlar:


13

Kafa karıştırıcı bir soyutlama katmanı ekliyorsunuz

API'niz çok temiz ve basit bir şekilde başlar. Bir HTTP POST, verilen parametrelerle yeni bir Para Yatırma kaynağı oluşturur. Ardından, API'nın temel bir parçası olmaktan ziyade bir uygulama ayrıntısı olan "eylemler" fikrini tanıtarak raydan çıkıyorsunuz.

Alternatif olarak bu HTTP konuşmasını düşünün ...

POST / kart / {kart kimliği} / hesap / {hesap kimliği} / Para Yatırma

AmountToDeposit = 100, farklı parametreler ...

201 OLUŞTURULDU

Yer = / kart / 123 / hesap / 456 / Mevduat / 789

Şimdi bu işlemi geri almak istiyorsunuz (teknik olarak, dengeli bir muhasebe sisteminde buna izin verilmemeli, ne hey):

SİL / kart / 123 / hesap / 456 / Depozito / 789

204 İÇERİK YOK

API tüketicisi, bir Para Yatırma kaynağı ile uğraştığını bilir ve üzerinde hangi işlemlere izin verildiğini belirleyebilir (genellikle HTTP'deki OPTIONS aracılığıyla).

Silme işleminin uygulanması bugün "eylemler" yoluyla gerçekleştirilmesine rağmen, bu sistemi örneğin C # 'dan Haskell'e geçirdiğinizde ve ön ucu "ikincil" eylem kavramının değer katmaya devam edeceğinin garantisi yoktur oysa, temel depozito kavramı kesinlikle öyle.

DELETE ve Para Yatırma alternatifini kapsayacak şekilde düzenleyin

Bir silme işleminden kaçınmak, ancak yine de Para Yatırma işlemini etkili bir şekilde kaldırmak için aşağıdakileri yapmanız gerekir (Para Yatırma ve Para Çekme için genel bir İşlem kullanarak):

POST / kart / {kart kimliği} / hesap / {hesap kimliği} / İşlem

Tutar = -100 , farklı parametreler ...

201 OLUŞTURULDU

Yer = / kart / 123 / hesap / 456 / transation / 790

Tam tersi olan (-100) yeni bir İşlem kaynağı oluşturulur. Bu, hesabın tekrar 0'a dengelenmesi ve orijinal İşlemin reddedilmesi etkisine sahiptir.

Gibi bir "yardımcı program" bitiş noktası oluşturmayı düşünebilirsiniz

POST / kart / {kart kimliği} / hesap / {hesap kimliği} / İşlem / 789 / Geri al <- KÖTÜ!

aynı etkiyi elde etmek için. Bununla birlikte, bu bir URI'nin anlambilimini bir fiil ekleyerek tanımlayıcı olarak keser. Tanımlayıcılardaki isimlere sadık kalmak ve işlemleri HTTP fiilleriyle kısıtlı tutmak daha iyidir. Bu şekilde tanımlayıcıdan kolayca bir kalıcı bağlantı oluşturabilir ve GET'ler vb. İçin kullanabilirsiniz.


3
+1 "teknik olarak buna dengeli bir muhasebe sisteminde izin verilmemelidir". Birisi fasulye saymayı biliyor. Bu ifade kesinlikle doğrudur, geri çevirmenin yolu, fonları geri alan başka bir işlem oluşturmaktır. Defteri kebir kayıtları, bir işlem tamamlandıktan sonra her zaman değişmez ve kalıcı olarak değerlendirilmelidir.
Evan Plaice

Yani, sorularımda, Sil / işlem / ... yerine Sil / depozito / ... olarak değiştirirsem, sorun değil mi?
Ocak'ta Mithir

2
@Mithir muhasebe kuralını tanımlıyordum. Standart çift girişli bir defter tutma sisteminde asla işlemleri kaldırmazsınız. Tarih işlendikten sonra insanları dürüst tutmak için değişmez kabul edilir. Sizin durumunuzda hala bir DELETE eylemi kullanabilirsiniz, ancak arka uçta (eski defteri kebir veritabanı tablosu) paranın kullanıcıya geri yatırılmasını temsil eden (yani geri veren) başka bir işlem eklersiniz. Ben fasulye sayacı değilim (muhasebeci) ama "Muhasebe İlkeleri I" dersinde öğretilen standart uygulamalardan biri.
Evan Plaice

2
(devam) Veritabanı günlükleri işlemleri benzer şekilde kullanır. Bu nedenle bir veri kümesini yalnızca günlükleri kullanarak çoğaltmak ve / veya yeniden oluşturmak mümkündür. İşlemler kronolojik olarak yeniden oynatıldığı sürece, veri kümesini tarihinin herhangi bir noktasından yeniden oluşturmak mümkün olmalıdır. Değişkenliği denklemden çıkarmak tutarlılığı sağlar.
Evan Plaice

1
Yeterince adil sadece İşlem olarak yeniden adlandırın.
Gary Rowe

1

REST'in var olmasının temel nedeni ağ hatalarına karşı dayanıklılıktır. Hangi amaçla tüm operasyonlar idempotent olmalıdır .

Temel yaklaşım makul görünmektedir, ancak DepositActionyaratılışın tanımlanma şekliniz sabit olması gereken kasıtlı değildir. Sahip olarak istemci yinelenen istekleri tespit etmek için kullanılacak benzersiz bir kimlik sağlar. Böylece yaratılış

PUT /card/{card-id}/account/{account-id}/Deposit/{action-id}
AmountToDeposit=100, different parameters...

Daha önce aynı içerikle aynı URL'ye başka bir PUT yapılırsa, içerik aynı ise yanıt 201 created, içerik farklıysa yine de hata olmalıdır. Bu, istemcinin isteği başarısız olduğunda yeniden iletmesine izin verir, çünkü istemci isteğin veya yanıtın kaybolup kaybolmadığını söyleyemez.

PUT kullanmak daha mantıklıdır, çünkü sadece kaynağı yazar ve idempotenttir, ancak POST kullanmak da herhangi bir soruna neden olmaz.

İşlem ayrıntılarına bakmak için müşteri GETaynı URL'yi, yani

GET /card/{card-id}/account/{account-id}/Deposit/{action-id}

ve geri almak için Silebilir. Ama aslında örnekte görüldüğü gibi para ile ilgili bir şey varsa, ben bunun yerine hesap verebilirlik (oluşturulan ve iptal edilen işlem iz kalır kalır) yerine eklenen "iptal" bayrakları ile PUTting öneririz.

Şimdi benzersiz bir kimlik oluşturma yöntemi seçmeniz gerekiyor. Birkaç seçeneğiniz var:

  1. Eklenmesi gereken exchange'de daha önce istemciye özgü öneki yayınlayın.
  2. Sunucudan boş benzersiz kimlik almak için özel bir POST isteği ekleyin. Bu isteğin idempotent olması gerekmez (ve gerçekten olamaz), çünkü kullanılmayan kimlikler gerçekten herhangi bir soruna neden olmaz.
  3. Sadece UUID kullanın. Herkes onları kullanıyor ve kimse MAC tabanlı olanlarla veya rastgele olanlarla herhangi bir sorun yaşamıyor gibi görünüyor.

2
Bildiğim kadarıyla POST idempotent değil. en.wikipedia.org/wiki/POST_(HTTP)#Affecting_server_state
Mithir

@Mithir: POST'un idempotent olduğu varsayılmaz; hala olabilir. Ancak tüm REST operasyonlarının idempotent olması gerektiği için POST'un temelde REST'te yeri yoktur.
Jan Hudec

1
Kafam karıştı ... okuduğum içerik ve bildiğim uygulama (ServiceStack, ASP.NET Web API), POST'un REST'te bir yeri olduğunu gösteriyor.
Mithir

3
REST'te idempotence, protokole veya yanıt kodlarına değil kaynağa atanır. Bu nedenle, HTTP üzerinden REST'te GET, PUT, DELETE, PATCH ve benzeri yöntemler idempotent olarak kabul edilir, ancak yanıt kodları sonraki çağrılar için değişebilir. POST, her çağrının yeni bir kaynak yaratması anlamında idempotenttir. Bkz Fielding var O POST kullanmak sorun yok .
Gary Rowe

1
İdempotent olmayan işlemlere dinlenme izni verilir. Bu iddia yanlıştır.
Andy
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.