RESTful API: Paylaşılan veya belirli URL’lere sahip HTTP fiilleri?


25

RESTful API oluştururken , aynı URL'de HTTP Fiilleri kullanmalı mıyım (mümkün olduğunda) veya işlem başına belirli bir URL oluşturmalı mıyım?

Örneğin:

GET     /items      # Read all items
GET     /items/:id  # Read one item
POST    /items      # Create a new item
PUT     /items/:id  # Update one item
DELETE  /items/:id  # Delete one item

Veya aşağıdaki gibi belirli URL’lerle:

GET     /items            # Read all items
GET     /item/:id         # Read one item
POST    /items/new        # Create a new item
PUT     /item/edit/:id    # Update one item
DELETE  /item/delete/:id  # Delete one item

Yanıtlar:


46

İkinci programınızda, fiillerinizi kaynaklarınızın URL'lerinde tutarsınız. HTTP fiilleri bu amaç için kullanılması gerektiği için bundan kaçınılmalıdır. Yok saymak, çoğaltmak veya geçersiz kılmak yerine, alttaki protokolü kullanın.

Şuna bir bakın DELETE /item/delete/:id, aynı bilgiyi aynı istek üzerine iki kez yerleştirin. Bu gereksizdir ve kaçınılması gerekir. Şahsen, bununla karıştırılırdım. API aslında DELETEistekleri destekliyor mu? deleteURL'ye yerleştirip yerine farklı bir HTTP fiili kullanırsam ne olur? Bir şeyle eşleşecek mi? Eğer öyleyse, hangisi seçilecek? Düzgün tasarlanmış bir API'nin müşterisi olarak, böyle sorular sormam gerekmiyor.

Belki de bir şekilde sorun çıkaran DELETEveya PUTtalep edemeyen müşterileri desteklemeniz gerekiyor . Bu durumda, bu bilgiyi bir HTTP başlığında iletirim. Bazı API'ler X-HTTP-Method-Overridebu özel amaç için bir başlık kullanır (ki bu zaten çirkindir). Tabii ki fiilleri yollara koymazdım.

İçin git

GET     /items      # Read all items
GET     /items/:id  # Read one item
POST    /items      # Create a new item
PUT     /items/:id  # Update one item
DELETE  /items/:id  # Delete one item

Fiiller hakkında önemli olan şey, HTTP spesifikasyonunda zaten iyi tanımlanmış olmaları ve bu kurallara uygun kalmaları, HTTP'nin anlamını anlayan, ancak uygulama anlamını anlamayan, uygulamanızın dışındaki önbellekleri, proxy'leri ve muhtemelen başka araçları kullanmanıza izin vermesidir. . Unutmayın ki, URL’lerinizde bunlardan kaçınmanızın nedeni, okunabilir URL’ler gerektiren RESTful API’lerle ilgili değildir. Gereksiz belirsizlikten kaçınmakla ilgilidir.

Dahası, bir RESTful API, bu fiilleri (veya herhangi bir alt kümesini), HTTP spesifikasyonuna uymadığı sürece herhangi bir uygulama semantiği grubuyla eşleyebilir. Örneğin, yalnızca kullandığı istediğinde izin verdiği tüm işlemleri ise GET olduğunu dinlendirici bir API inşa etmek pekala mümkündür hem kasa ve idempotent . Yukarıdaki haritalama, kullanım durumunuza uyan ve teknik özelliklerle uyumlu bir örnektir. Bu şekilde olmak zorunda değil.

Ayrıca, gerçek anlamda bir RESTful API'nin, bir REST'in temel varsayımlarından biri olan HATEOAS (Uygulama Durumunun Motoru Olarak Hiper Metin) ilkesine uyduğunuz sürece, mevcut URL'lerin kapsamlı dokümantasyonunu okumak için hiçbir zaman bir programlayıcıya gereksinim duymaması gerektiğini lütfen unutmayın . Müşteri uygulaması, olası uygulama durum geçişlerini anlamak için bunları anlayabildiği ve kullanabildiği sürece, bağlantılar insanlar için tamamen anlaşılmaz olabilir.


4
Yokluğunda PUTve DELETEben bir sorgu dizesi ile farklılaştırarak, yola öyle değil ekleyerek yana olacaktır. Mevcut bir işlem için bir sorgu dizesi değişikliği değil; bu ayrı bir operasyon.
Robert Harvey,

4
@RobertHarvey bu durumda, yine de bir kesmek derdim. Söylediğiniz gibi, bu bir işlem ve RESTful olmayı hedefleyen bir API tasarlarken yola koyduğum bir şey değil. Sorgu dizgisine yerleştirmek daha az istilacı görünüyor. Önbelleğe almayı önler ancak bu tür isteklere verilen yanıtların yine de önbelleğe alınması gerektiğini düşünmüyorum. Ayrıca, API tüketicisinin URL'yi ayrıştırmadan veya oluşturmadan yöntemi kolayca belirtmesini sağlar. İdeal olarak, gerçekten RESTful bir API, müşterilerin URL'leri kendilerinin oluşturmasını gerektirmeden köprüler sağlamalıdır.
toniedzwiedz

Tüm fiillere sahip değilseniz, yine de tamamen RESTful değil, değil mi?
Robert Harvey,

@RobertHarvey true ancak bunları amaçlanan tasarım olarak değil, bir geri dönüş olarak kabul ediyorum. API'nin gerçek HTTP yöntemlerini desteklemesi gerektiğini düşünüyorum ve bazı müşteriler onları herhangi bir nedenle uygulayamazlarsa, kullanımlarını bu sorgu paramlarıyla değiştirebilirler. Bir proxy bile bunları anında alabilir ve istekleri orijinal HTTP fiilleri kullanarak isteklere dönüştürebilir, böylece sunucunun bakım yapmasına bile gerek kalmaz. Etrafında çok az API var RESTful. Genel web API'leri söz konusu olduğunda, gerçekten bir zevk meselesi. Şahsen ben temiz URL'ler için giderdim. IMHO'yu anlamak daha kolay.
toniedzwiedz

1
@RobertHarvey açıklandığı gibi, onları kullanmak için amaçlanan bir yol değildir. Bunu sadece müşteri sınırlamalarının üstesinden gelmek zorunda kaldığın zaman için iki kötülükten daha az buluyorum. Böyle bir API için bir belgeyi okuduğumu hatırlıyorum, ancak bulmak için tarayıcı geçmişim / yer imlerimde biraz kazı yapmam gerekecek. Şimdi düşünüyorum da, bu durumda bir başlık daha iyi olabilir. Katılıyor musun?
toniedzwiedz

14

İlki.

Bir URI / URL bir kaynak tanımlayıcısıdır (adındaki ipucu: üniforma kaynak tanımlayıcısı). İlk kuralda, "GET / user / 123" yaptığınız zaman konuşulan ve "DELETE / user / 123" yaptığınız zaman konuşulan kaynak açıkça aynı URL’ye sahip oldukları için aynı kaynaktır.

İkinci sözleşmeyle, "GET / user / 123" ve "DELETE / user / delete / 123" öğelerinin aslında aynı kaynak olduğundan emin olamazsınız ve kaynaktan ziyade ilgili bir kaynağı sildiğiniz anlamına gelir. kendisi, bu yüzden silmenin /user/delete/123aslında silinmesi şaşırtıcı olacaktır /user/123. Her işlemin farklı URL’lerde çalışması varsa, URI artık bir kaynak tanımlayıcısı olarak çalışmaz.

Söylediğinizde DELETE /user/123, "kimliğini 123 'kullanıcı kimliğiyle sil'" diyorsunuz. Eğer söylerseniz DELETE /user/delete/123, ima ettiğiniz gibi görünen şey, '' 123 numaralı kullanıcı temsilcisinin kimliğini silerek silmek '', yani muhtemelen söylemek istediğiniz şey değil. Ve bu durumda daha doğru bir fiil kullansanız bile: "POST / user / delete / 123", "kimliği 123 olan kullanıcı temsilcisine bağlı işlemi yap" diyen ", yine de bir kaydı silmek için bir dolambaçlı yoldur (Bu, fiillerin İngilizce olarak isimlendirilmesine benzer).

URL hakkında düşünmenin bir yolu, nesneye yönelik programlamada nesnelere işaretçiler ve nesneler olarak kaynaklar gibi davranmaktır. Bunu yaptığınızda GET /user/123, DELETE /user/123:, nesnenin içinde yöntemleri olarak onları düşünüyorum düşünebiliriz [/user/123].get(), [/user/123].delete()nerede [](eğer işaretçiler var bir dil biliyorsanız) operatörünü dereferencing bir işaretçi gibi ama URL'ler içindir. REST'in temel ilkelerinden biri tek biçimli arayüzdür, yani geniş bir kaynaklar / nesneler ağındaki her şey için çalışan küçük ve sınırlı bir fiil / yöntem setine sahip olmak.

Bu nedenle, birincisi daha iyidir.

Not: Tabii ki, bu REST'e en saf biçimde bakıyor. Bazen pratiklik saflığı yener ve beyin ölmüş müşterileri veya uygun REST yapmayı zorlaştıran çerçeveler için taviz vermeniz gerekir.


OOP örneği için +1 :)
53777A

6

(üzgünüm, benim ilk kez / edit / ve / delete / in (2) özledim ...)

URI'nin fikri, bir yöntem çağrısı yerine, adreslenebilir bir kaynağın bir tanımlayıcısı olmasıdır . Bu nedenle, URI belirli bir kaynağa işaret etmelidir. Ve eğer URI'yi göz ardı ederseniz, her zaman aynı kaynağı edinmelisiniz.

Yani, URI'leri bir veritabanındaki satırın Birincil Anahtarını düşündüğünüz gibi düşünmelisiniz. Benzersiz bir şeyi tanımlar: Evrensel Kaynak Tanımlayıcısı.

Dolayısıyla, çoğul veya tekil kullanıyor olsanız da, URI, bir çağrıdan ziyade bir tanımlayıcı olmalıdır . Ne çalışıyoruz yapmak yönteminde gider, yani: GET (get), PUT (oluşturun / güncelleme), SİL (silme) veya POST (her şey).

Bu nedenle, "/ item / delete / 123" bir kaynağa işaret etmediği için REST'i keser, daha çok bir yöntem çağrısıdır.

(Ayrıca, yalnızca anlamsal olarak, bir URI GET yapabilmeli, eski olduğuna karar vermeli ve daha sonra aynı URI'yi SİLMELİSİNİZ olmalıdır - çünkü bu bir tanımlayıcıdır. o zaman bu HTTP anlambilimine aykırıdır. Kaynak başına 1 veya daha fazla URI yayınlıyorsunuz.)

Şimdi, hile şudur: Bir kaynağın ne olduğu ve kaynak olmadığı konusunda net bir tanım yoktur, bu nedenle REST'teki ortak nokta bir "işlem ismi" tanımlamak ve URI'yi buna işaret etmektir. Bu hemen hemen bir kelime oyunu, ancak anlambilimine uygundur.

Yani, örneğin, bir nedenden dolayı bunu gerçekten kullanamazsanız:

DELETE /items/123

Dünyaya bir “temsilci” işleme kaynağınız olduğunu ve kullanabileceğinizi beyan edebilir

POST /items/deletor  { id: 123 }

Şimdi, bu RPC'ye (Uzaktan Prosedür Çağrısı) çok benziyor, ancak POST şartnamesinin "veri işleme" yan tümcesinde, HTTP belirtiminde belirtilen büyük boşluktan düşüyor.

Ancak, bunu yaparken tür istisnai bir olduğunu ve eğer olabilir ekleme yapılması için ortak silme için SİL, / güncelleme oluşturmak için PUT ve POST kullanın, oluşturma ve her şey, o zaman gerekir , HTTP daha standart kullanım olduğu için. Ancak "taahhüt etmek" veya "yayınlamak" veya "geri çevirmek" gibi zor bir durumunuz varsa, bir işlemci adının kullanılması durumu REST uzmanlarına cevap verir ve hala ihtiyacınız olan semantikleri 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.