Bir REST web hizmetinde bir eylemi tetiklemek için hangi HTTP fiilini kullanmalıyım?


80

Bir RESTful web servisi uyguluyorum ve mevcut işlemlerden biri olacak reload. Yapılandırmaları, önbelleği vb. Yeniden yüklemek için kullanılacaktır.

Bunun GETgibi bir URI'ye basit bir şekilde başladık : ${path}/cache/reload(parametre iletilmez, sadece URI çağrılır). Verilerin bir GET isteğiyle değiştirilmemesi gerektiğini biliyorum.

RESTful web hizmetinde bir eylem / komut çağırmak için kullanılacak doğru fiil hangisidir?

Yeniden yükleme, kendi önbelleğini / configuration / etc dosyasını yeniden yükleyen REST web servisinin bir komutudur. İstemciye bilgi döndüren bir yöntem değildir.

Muhtemelen yapmaya çalıştığım şey REST değil, ama yine de bu şekilde yapılması gereken bir şey. reloadYöntem yalnızca uygulama kapsamında duygusu ve üzerinde duruldu çoğu cevapları yapan gerçek bir örnekti, ama aslında, ben sadece CRUD yapmaz bir eylem tetiklemek için hangi fiil bilmemiz gereken ama hala / veri değiştirir durum.

Bu konuyla ilgili Stack Overflow ile ilgili bu asnwer'ı buldum: https://stackoverflow.com/questions/16877968/


1
"Yeniden yüklemek", görüntülenecek verileri tazeleyen bir uygulamanın anlamıdır? Yeniden yükleme ve tekrar veri alma arasında bir fark var mı?
Sean Redmond

1
@SeanRedmond Hayır, veriler müşteriye gönderilmez. Aslında, müşteri REST web servisine çalıştırılacağını ve dahili komutu (yeniden yükle) olduğunu söylüyor. Şunu gibi bir şey: "veritabanında birçok yapılandırma değiştirildi, bu nedenle REST web hizmeti, bunları şimdi belleğinize yeniden yükleyin".
Renato Dinhani

Siteler arası çift kopya: stackoverflow.com/q/15340946/319403
cHao

Uygun isteklerde bir başlık parametresi kullanmayı düşündünüz mü? Bu çok önbellek yenileme gibi geliyor ...
Guran

Yanıtlar:


25

Bu işlem için uygun bir fiil olduğunu sanmıyorum çünkü bu işlem gerçekten "RESTful" değil. "S" ve "t" "devlet aktarımı" anlamına gelir ve burada hiçbir şey aktarılmamaktadır. Veya, başka bir deyişle, en katı tanımıyla, PUT ve POST gibi fiiller her zaman bir isim ile kullanılır ve “yeniden yükle” fiili vardır.

Bu yeniden yükleme RESTful olmayabilir, ancak yine de yararlı olabilir ve bunu yapmanın bir yolunu seçmeniz ve bunun alışılmadık olduğunu açıklamanız gerekir. GET muhtemelen en basit olanıdır. Ancak yorumlarda oldukça fazla kuşkuculuk var, bu yüzden bu yeniden yükleme işleminin gerekli olup olmadığını düşünmelisiniz, çünkü yapması gereken şeyi başka bir şey yapmıyor.


Bunun RESTful olmadığına, ancak yararlı olabileceğine katılıyorum. Bence bir PUT tavsiye etmelisiniz, çünkü bu muhtemelen yanlış ama nullimpotent değil.
Aaron Greenwald

@Aaron, idempotent ve nullimpotent'in karşılaştırılması her şey yolunda ve iyidir, ama ne zaman önemsiz olduğunu ne zaman belirlersiniz?
Craig,

@Craig, birçok kez çalıştırılmasının, bir kez çalıştırmanın aynı etkiye sahip olması önemsizdir. Bir veya birkaç kez çalıştırılması, sunucu üzerinde sıfır kez çalıştırılması ile aynı etkiye sahip olması halinde geçersiz sayılır. en.wikipedia.org/wiki/Idempotence
Aaron Greenwald

5
@AaronGreenwald “notimpotent” [not-im-poht-nt] [not-im-pawr-tnt] - sıfat - 1. “Sıfır” sıfatının “önemli” kelimesi üzerine bir oyun, “önemli” 2. Mizah… ;-)
Craig

@Craig Bunu tamamen özledim :)
Aaron Greenwald

75

RESTful olmak istiyorsanız, fiilin bir eylem gerçekleştireceğini düşünmeyin , müşteri bir şey yaptıktan sonra kaynağın içinde olmasını istediğiniz durumu düşünün.

Bu yüzden yukarıdaki örneklerden birini kullanarak e-posta gönderen bir e-posta sıranız var. Müşterinin bu e-postayı, duraklatılmış veya durdurulmuş veya herhangi bir şey durumuna sokmasını istiyorsunuz.

Bu nedenle istemci, bu kaynak için sunucuya yeni bir durum PUTS. Bu JSON kadar basit olabilir

PUT http://myserver.com/services/email_service HTTP/1.1
Content-Type: text/json

{"status":"paused"}

Sunucu mevcut durumdan ("çalışıyor" deyin) "duraklatıldı" durum / duruma nasıl ulaşılacağını belirler.

Eğer müşteri kaynakta bir GET yaparsa, şu anda içinde bulunduğu durumu iade etmelidir ("duraklatıldı" deyin).

Bu şekilde yapmanın nedeni ve REST'in bu kadar güçlü olmasının nedeni, NASIL'ı sunucuyu bu duruma getirmek için NASIL terketmenizdir.

Müşteri sadece "Şimdi olmanız gereken durum budur" der ve sunucu bunun nasıl başarılacağını bulur. Veritabanındaki basit bir çevirme olabilir. Binlerce eylem gerektirebilir. Müşteri umursamıyor ve bilmek zorunda değil.

Böylece, sunucunun bunu nasıl yaptığını ve müşterinin umursamadığını tamamen yeniden yazabilir / yeniden tasarlayabilirsiniz. Müşterinin, herhangi bir dahili değil, bir kaynağın farklı durumlarından (ve temsillerinden) haberdar olması gerekir.


2
Endişelendiğim kadarıyla bu doğru cevap. Sunucudaki verileri tazelemek kesin bir işlem değildir ve GETkullanımı tamamen uygunsuz bir fiildir. PUTişlemin, önbelleğin "yeniden yüklenen durumunu" "yeniden yüklenen" olarak güncellemesi olarak düşünülebileceği için en uygun fiildir.
Jez,

@Jez Buradaki cevapların arasında bunu da tercih ederim. E-posta metaforu ile tutunan, bu hazırlıksız yok "gönderme" haline sokuyor yerine sadece posta göndererek düşünmek ilk başta garip hissediyorum göndererek onu (bir eylem). Ancak, bunu düşünüyorsanız, bu gerçekten "giden kutusuna" koymakla aynı şeydir. Aslında, posta sisteminin kendisi, göndermesini söylediğinizde dahili olarak bu şekilde sıraya sokuyordur. Böylece, API postaları "gönderme" durumuna getirmenize izin verebilir ve API kendisini bunun ötesinde açıklamak zorunda değildir.
Craig,

Dolayısıyla, mesajın henüz gitmesini istemiyorsanız, yayınlanması gereken tarih / saat ile "programlanmış" duruma getirin. Tamamlanmadıysa, "taslak" durumunda vb. (Veya dolaylı olarak / varsayılan olarak) koyarsınız.
Craig

... bu durumda POST'u PUT'a tercih edeceğimi düşünmeme rağmen, PUT'un aynı zamanda iddiasız olması da gerekiyor, ancak POST'un böyle bir kısıtlaması yok.
Craig,

1
Bunu yapabilirsin, ama sonuçta kare bir çiviyi yuvarlak bir deliğe sığdırmaya çalışıyor. İstemcinin sunucuyu herhangi bir şeyi "yeniden yüklemesi" için tetiklemesinin bir nedeni yoktur, bu yalnızca zayıf mimari tasarımdır. Sunucu, her aramada veya sabit bir zaman aralığında dahili durumunu güncelleyebilir. İstemciye, sunucuya bir kaynak durumu için gerçek bir istekten bağımsız bir şeyi yeniden yüklemesini söylemesi, RESTful mimarisi değildir.
Cormac Mulhall

32

Kabul edilenler de dahil olmak üzere diğer cevapların bazıları bir GET kullanmanızı tavsiye eder (çok istekli olmasa da).

Katılmıyorum.

Her şeyden önce, diğerleri size bunun ideal olmadığını ve gerçekten RESTful olmadığını söylüyor. Uygun bir RESTful senaryosunda, sunucudaki kaynakları değiştirir ve bu kaynakları ekler, günceller, siler, alır vb. Bir PUT, istek tamamlandığında kaynağın ne olması gerektiğini temsil eden bir bilgi yükü göndermeli ve POST, sunucuya eklenecek bir kaynağı temsil eden bir bilgi yükü göndermelidir. Ve bir GET sunucuda bir kaynak döndürmelidir.

RESTful olmayan bir RPC'niz (uzaktan prosedür çağrısı) var - sunucuda bir şeyler yapmak istiyorsunuz. Bu nedenle tamamen RESTful bir API oluşturmaya çalışıyorsanız, ne yaptığınızı tekrar gözden geçirmelisiniz.

Bununla birlikte, bazen kuralları biraz eğmeniz gerekir. Özellikle halka maruz kalmayacak bir iç api geliştiriyorsanız, değiş tokuşa değeceğine karar verebilirsiniz.

Bunu yaparsanız, bir PUT veya POST öneriyoruz, olsun veya olmasın RPC bağlı olan İdempotent ya da değil.

Genel olarak, HTTP PUT'un SQL UPDATE ile eşleştiğini ve HTTP POST'un SQL INSERT ile eşleştiğini söylüyoruz, ancak bu kesinlikle doğru değil. HTTP PUT'un önemsiz olması ve HTTP POST olması gerekmediğini belirtmenin daha saf bir yolu. Bu, aynı PUT isteğini, yan etkisi olmadan istediğiniz kadar çağırabileceğiniz anlamına gelir. Bir kez aradığınızda, tekrar aramak zararsızdır. Ancak, demek istemediğiniz sürece tekrar tekrar POST isteklerini aramamalısınız - her POST sunucudaki verileri tekrar değiştirir.

Sizin durumunuzda, bu yeniden yükleme işlevine ihtiyacınız varsa, bir PUT öneriyorum, çünkü güvenilir gibi görünüyor. Ama yine de diğerlerinin buna ihtiyaç duymama konusunda söylediklerini düşünmenizi rica ediyorum.


6

POSTve PUTbir varlık bir web sunucusuna göndermek için kullanılan HTTP fiilleridir. İle PUT, gönderen varlık istediğini uymuyor verilen URI, konumundaki kaynağa yapılan (yeni) temsilidir. POSTvarlığın kaynağın yardımcı verileri olduğu geleneksel form işleyicisi içindir, bu yüzden kazanan budur. İşletme, komutu veya eylemi içerecektir (örn. "Action = yeniden yükle").

Bununla birlikte, söz konusu komutun muhtemelen bir REST arayüzü aracılığıyla ifşa edilmemesi gerektiği belirtildi. Verilerin başka bir kanaldan (ör. Dosya sistemi, DB istemcisi gibi) değiştirilebilmesi nedeniyle “yeniden yükleme” zorunluluğu ortaya çıkıyor. Önbellekler şeffaf olmalıdır. Dahası, HTTP istekleri atomik olmalıdır, hatta diğer kanallardan gönderilen mesajları da dikkate alır. Yapılandırma ayarları için "yeniden yükle" komutu sunmak gereksiz bir karmaşıklık gibi görünüyor; gerektiren bir kırılgan tasarım. Başka bir kanal aracılığıyla yapılan bir güncellemeden sonra temizleme işlemine "yeniden yükleme" yapmak, bir kanalın tüm konuşmayı içermediğinden kirli. Bunun yerine, şunlardan birini düşünün:

  • tamamen REST ile güncelleme yapmak
  • komutları diğer kanala maruz bırakmak
  • eylemlerin otomatikleştirilmesi

Diğer seçeneklerin neler olduğuna bağlı olarak, bu seçeneklerden bazıları geçerli olmayabilir.

Ayrıca bakınız " REST'ta POST-POST ".


Teşekkür ederim. Düzenlemenin "iç" ini kaldırdım çünkü aslında "yeniden yükleme" yöntemi herkese açıktı. Sadece web servisinin kendisine atıfta bulunduğunu kastediyordum. Bence "eylem" göndermenin iyi bir yaklaşım olacağını düşünüyorum.
Renato Dinhani

@ RenatoDinhaniConceição: "iç" olmadan bile, hala kokuyor. Tasarımın iyi olup olmadığı hakkında yeni bir soru sormanız size yardımcı olabilir.
outis

4

Bir müşteri isteğinin neden böyle bir şeyi yenilemek için açıkça bir çağrı yapması gerektiğini tartışacağım. Bunun, GET'in daha tipik bir uygulamasında gizli bir mantık olması gerektiği gibi geliyor (Ie Pull verileri, ancak hizmet çekilmeden önce verilerde bir yenileme yapar) veya arka uçtaki istemciden uzaktaki başka bir tetikleyici tarafından.

Sonuçta, data / config'in sadece sonraki çağrılarda güncel olması gerekiyordu, bu yüzden veri yenilemek için tembel ve istekli bir çağrıya daha fazla eğildim. Açıkçası burada çok fazla varsayım var, ancak bu kadar açık ve bağımsız bir aramanın gerekliliğini yeniden değerlendirmek için bir adım geri atıyorum.


Düzenlemeye bak. "yeniden yükle", verileri döndüren bir komut değildir. REST web servisinin kendisine atıfta bulunur. Genel anlamda sorum, bir REST web servisindeki eylemleri tetikleme ile ilgilidir. Diğer bir örnek olabilir: email_queue/stop_sending_emails. Ben sadece bir RESTful arayüzü kullanarak bir şeye komut vermek istiyorum.
Renato Dinhani

5
Hala aynı fikirdeyim. Çağırma SIGHUP bilgisayar birisi o sinyale erişimi olan yerel kimin oturum güveneyim beri yerel bir süreç, mantıklı. Ama vatansız, internete erişilebilir bir protokol için? Belki de web servisi, sorgulama veya dosya izleme yoluyla gerektiğinde otomatik olarak yeniden yüklenmelidir. Bu çağrı tamamen gereksiz olmalı .

1
Katılıyorum. Yapılandırma ve önbellekleme gibi şeylerin müşteriye şeffaf olması amaçlanmıştır. Belki de bize son noktanızın çağrılacağı bir durum hakkında daha somut bir açıklama yapmalısınız.
Benjamin Hodgson

3

Neden eyleme bir kaynak gibi davranmıyorsunuz? Bu nedenle, önbelleği güncellemek istediğinizden, sisteminizde yeni bir eylem POST olacaktır.

Purists için, bunun için özel bir URL'ler olabilir. Bunu genişletebileceğinizi ve gerçek eylemleri bir veritabanında (veya hangi depolama alanında olursa olsun) tarih, durum, kullanıcı vb. İle günlüğe kaydedebileceğinizi unutmayın ... Sadece düşüncelerim.

Genel sistem genelinde işlem / işlemler / {eylem}

Kaynak türüne özgü işlem / actions / {resource} / {action}

Bir kaynağa / işleme özel işlem / {resource} / {id} / {action}

Senin durumunda, önbellek muhtemelen sistem çapında / actions / reload_cache


0

Bir REST web hizmetinde bir eylemi tetiklemek için hangi HTTP fiilini kullanmalıyım?

Bir REST servisinin detaylarını düşünürken, bu buluşsal düşünceyi göz önünde bulundurmak genellikle yararlı olacaktır: bunu bir web sitesi ile nasıl uygularsınız?

HTML, yalnızca GET ve POST isteklerini tanımlayabilir. Yani başlayabiliriz orada arama.

GETuygun? Bu soruyu cevaplamak için, müşterilerin ve ara bileşenlerin yapmasına izin verilen varsayımları düşünmemiz gerekir GET. Anlamsallığı GETolan güvenli

istemci, hedef bir kaynağa güvenli bir yöntem uygulanmasının bir sonucu olarak kaynak sunucuda herhangi bir durum değişikliği istemez ve beklemez. Benzer şekilde, güvenli bir yöntemin makul bir şekilde kullanılmasının kaynak sunucuda herhangi bir zarara, mülk kaybına veya olağandışı bir yüke neden olması beklenmez.

Bu nedenle, sonuç, müşterilerin ve ara bileşenlerin kendi endişelerini gidermek için gerektiği kadar GET talebini başlatma konusunda takdir yetkisi olmasıdır. Örümcekler dizinlerini güncellemek için kaynakları ayırt etmeksizin alabilir. Önbellekleri önceden getirebilir. Güvenilmez bir ağda, en az bir yanıtı sağlamak için kayıp mesajlar gerektiği kadar sık ​​tekrar denenebilir.

Yapılandırmaları, önbelleği vb. Yeniden yüklemek için kullanılacaktır.

Bunlar yapılması pahalı şeyler ise, belki de müşterilerin bu istekleri kendi takdirine bağlı olarak yapmalarını istemezsiniz.

POSTÖte yandan, etkili bir şekilde sınırlandırılmamıştır - bu, genel müşterilerin yapmasına izin verilen varsayımları büyük ölçüde azaltır. Spekülatif POST istekleri yapan bileşenlere sahip değilsiniz, çünkü bunu yapmaktan mahrum kalacaklardı - standarttaki hiçbir şey tamam değil diyor.

PUT, PATCH, DELETE... bunlardan daha fazla spesifik semantik ile güvensiz yöntemler POST; uygun olup olmadıkları kaynak modelinize bağlı olacaktır.

Akılda tutulması gereken önemli bir fikir, HTTP yöntemlerinin belge etki alanına ait olmasıdır (Bkz. Jim Webber'in 2011 konuşması ), tanımladığınız etkilerin büyük olasılıkla belge etki alanının bir parçası olmadığı, ancak belgeler değiştirildiğinde yan etkilerin olduğu . Bu, çalışmalarınızı gerçekleştirmek için belgelerinizi nasıl düzenlediğiniz konusunda size çok fazla özgürlük verir.

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.