REST API - PUT DELETE POST GET neden kullanılmalı?


155

Bu yüzden, REST API'leri oluşturma ile ilgili bazı makalelere bakıyordum. Ve bazıları her türlü HTTP isteğini kullanmanızı önerir: like PUT DELETE POST GET. Örneğin index.php oluşturur ve API'yı şu şekilde yazarız:

$method = $_SERVER['REQUEST_METHOD'];
$request = split("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    ....some put action.... 
    break;
  case 'POST':
    ....some post action.... 
    break;
  case 'GET':
    ....some get action.... 
    break;
  case 'DELETE':
    ....some delete action.... 
    break;
}

Tamam, verilmiş - Web hizmetleri hakkında henüz fazla bir bilgim yok (henüz). Ancak, JSON nesnesini normal POSTveya GET(yöntem adı ve tüm parametreleri içeren) aracılığıyla kabul etmek ve ardından JSON'da yanıt vermek daha kolay olmaz. PHP'ler aracılığıyla kolayca serileştirebilir / serisini kaldırabilir json_encode()ve json_decode()farklı HTTP istek yöntemleriyle uğraşmak zorunda kalmadan bu verilerle istediğimizi yapabiliriz.

Bir şey mi kaçırıyorum?

GÜNCELLEME 1:

Tamam - çeşitli API'leri araştırıp XML-RPC , JSON-RPC , SOAP , REST hakkında çok şey öğrendikten sonra , bu tür API'nin sağlam olduğu sonucuna vardım. Aslında yığın değişimi sitelerinde bu yaklaşımı kullanıyor ve bu insanların ne yaptıklarını bildiklerini düşünüyorum. Stack Exchange API .


4
Neden bir JSON yükünü zorlamalısınız? JSON yoksa ve sade eski bir GET olursa?
Mike DeSimone

Yanıtlar:


200

Fikri RE sunumsal S Tate T ransfer is not mümkün olan en basit şekilde verilere erişme hakkında.

Verilere erişmek / işlemek için mükemmel geçerli bir yol olan JSON'a erişmek için posta istekleri kullanmanızı önermiştiniz.

REST, verilere anlamlı erişim için bir metodolojidir . REST'te bir istek gördüğünüzde, verilerde neler olduğu hemen anlaşılmalıdır.

Örneğin:

GET: /cars/make/chevrolet

muhtemelen chevy arabaların bir listesini döndürecek. İyi bir REST API'si sorgu dizesine benzer ?output=jsonveya ?output=htmlerişimcinin bilgilerin hangi formatta kodlanması gerektiğine karar vermesine izin verecek bazı çıkış seçeneklerini bile içerebilir .

Nasıl bir REST API içine makul anonim veri yazmaya hakkında düşünme biraz sonra ben en iyi yolu gibi zaten varolan dosya uzantısı üzerinden olacağını açıkça veri türünü belirtmek için sonucuna sonra .js, .json, .htmlveya .xml. Eksik bir dosya uzantısı varsayılan olarak hangi formatta olursa olsun (JSON gibi); desteklenmeyen bir dosya uzantısı 501 Not Implementeddurum kodu döndürebilir .

Başka bir örnek:

POST: /cars/
{ make:chevrolet, model:malibu, colors:[red, green, blue, grey] }

muhtemelen db'de ilişkili renklerle yeni bir chevy malibu oluşturacak. Diyorum olasılıkla DİNLENME API doğrudan veritabanı yapısı ile ilişkili gerekmez olarak. Bu sadece bir maskeleme arayüzüdür, böylece gerçek veriler korunur (bir veritabanı yapısı için erişimciler ve mutantlar gibi düşünün).

Şimdi idempotence konusuna geçmemiz gerekiyor . Genellikle REST , HTTP üzerinden CRUD uygular . HTTP kullanır GET, PUT, POSTve DELETEistekleri için.

REST Çok basit uygulama olabilir aşağıdaki REZİL eşlemesi kullanın:

Create -> Post
Read   -> Get
Update -> Put
Delete -> Delete

Bu uygulama ile ilgili bir sorun var: Post idempotent olmayan bir yöntem olarak tanımlanır. Bu, aynı Post yönteminin sonraki çağrılarının farklı sunucu durumlarıyla sonuçlanacağı anlamına gelir . Get, Put ve Delete, idempotent; Bu, onları birden çok kez çağırmanın aynı sunucu durumuna neden olması gerektiği anlamına gelir.

Bu, aşağıdaki gibi bir isteğin olduğu anlamına gelir:

Delete: /cars/oldest

aslında şu şekilde uygulanabilir:

Post: /cars/oldest?action=delete

Buna karşılık

Delete: /cars/id/123456

bir kez çağırırsanız veya 1000 kez çağırırsanız aynı sunucu durumuna neden olur.

oldestÖğenin kaldırılmasını ele almanın daha iyi bir yolu istemek olacaktır:

Get: /cars/oldest

ve IDsonuçta elde edilen verilerden bir deleteistekte bulunmak için kullanın:

Delete: /cars/id/[oldest id]

Bu yöntemle ilgili bir sorun, /carsne zaman /oldestistendiği ile deleteyayınlanma tarihi arasında başka bir öğe eklenmesi olabilir .


3
@Ve bu bir dizi nedenin birleşimidir: HTTP yönergelerine uymak, işler değiştiğinde (muhtemelen) geriye dönük uyumluluk sorunlarının daha az olacağı anlamına gelir; POST aracılığıyla bir html formunun kullanılması kullanıcıyı aynı verilerin birden çok gönderimi için uyarır (bu, idempotent olmayan bir işlemi önlemek içindir); iyi tanımlanmış en iyi uygulamayı takip etmek, iyi ... en iyi uygulamadır. Dinlenme, uygun gördüğünüz gibi kullanmanıza izin veren belirli bir uygulama göz önünde bulundurularak tanımlanmaz. Tüm HTTP hata kodlarından ve istek yöntemlerinden yararlanmanızı öneririm, ancak istediğiniz gibi yapmanıza izin verilir
zzzzBov

4
Yani bu cevapla ilgili sorun (iyi bir cevaptır, ancak tam değildir) sorduğu ana soruyu ele almamasıdır: Özel JSON verileri yerine neden HTTP fiilleri ve URI kullanıyorsunuz (belki bir çeşit JSON tabanlı API çağırma sözdizimi). Özel JSON sözdizimini "hemen ... verilerle neler olduğunu anlayacak şekilde" yapabilirsiniz. Yapamayacağınız şey, tüm REST kurallarını izleyen bir API ile yerleşik tesisleri ve ağ katmanlarını HTTP'nin üstünde kolayca kullanmaktır. Cevabım mükemmel değil elbette;)
Merlyn Morgan-Graham

4
@Andre: Wiki girişinin kullandığı örnekler kimlik doğrulama, önbellekleme ve içerik türü anlaşmasıdır. Şimdi bunun hakkında daha fazla düşündüğüme göre, bunları RPC tarzı arayüzlerle kullanabilirsiniz, ancak cazip genellikle kendi sisteminizi sıfırdan uygulamak veya mevcut bir sisteme bir entegrasyonu kodlamak olacaktır. REST ile yerleşik entegrasyonu kullanabilir ve web sunucusunda yönetebilirsiniz. Bu, daha düşük birleştirme anlamına gelir, bu da daha az uygulama yapmanız gerektiği anlamına gelir ve uygulamanızın gelecekte daha az kod ve test etkisi ile seçenekleri değiştirmek için çok daha esnek olduğu anlamına gelir.
Merlyn Morgan-Graham

10
DELETE: / cars / oldest yerine, GET: / cars / oldest ve ardından bir DELETE? Bu şekilde, iki ayrı idempotent komutunuz olur.
Neil

3
+ 1; Bu iyi bir cevap olduğunu kabul ediyorum (eğlence ve kar için tekrar üzerinden gidiyorum). POST: /cars/oldestDELETE yerine geçmek çok mantıklı değil. Gibi bir şey - POST: /cars/oldest/deletekudretini, tho ben Neil'in çözüm daha iyi gibi ben düşünüyorum. Doğrudan silme işleminin get-id-delete-id çözümüne verdiği tek avantaj atomisitedir. Böyle bir şeyi uygulamadan önce, tartışmasız bir senaryo ile net bir iş gerekçesi istiyorum. Tüm nesneler / URL'lerdeki tüm fiilleri desteklemenize gerek yoktur.
Merlyn Morgan-Graham

39

Bu bir güvenlik ve sürdürülebilirlik sorusudur.

güvenli yöntemler

Mümkün olduğunda, olası güvenlik açığını sınırlamak için GET ve HEAD gibi 'güvenli' (tek yönlü) yöntemleri kullanmalısınız.

idempotent yöntemler

Mümkün olduğunda, GET, HEAD, PUT ve DELETE gibi yan etkilere sahip olmayan ve bu nedenle daha az hataya eğilimli / kontrolü daha kolay olan 'idempotent' yöntemleri kullanmalısınız.

Kaynak


1
Maalesef PUT ve DELETE idempotent yöntemleri nasıl? Sunucunun durumunu ve verilerini etkilerler!
Mahmud El Kudsi

27
@Bilgisayar: Aynı PUT veya aynı DELETE öğesinin yapılması aynı son duruma neden olur. Yani neyi "İdempotent" yoludur.
Ignacio Vazquez-Abrams

4
Daha fazla açıklama için: tek bir uygulama ve bunun sonucunda ortaya çıkan birkaç uygulamanın her ikisi de aynı sonucu verirse, F operasyonu idempotenttir. Daha kesin olarak F, yalnızca F (x) = F (F (x)) olduğunda ve aynı zamanda idempotenttir. Örneğin, Sil bir öğeyi sildiğinizden, bir öğeyi bir kez sildiğinizde veya birkaç kez sildiğinizde sonuç aynıdır: öğe ilk silme uygulamasıyla yalnızca bir kez silinir ve silme ikinci veya üçüncü uygulamasında hiçbir şey olmaz.
qartal

1
Ancak oluşturma açısından, bir create komutuyla yeni bir kayıt oluşturduğunuzda ve aynı komutu tekrar yayınladığınızda, (her ikisi de aynı bilgileri yansıtsa da) iki kayıt oluşturulur (muhtemelen).
qartal

qartal - idempotent için fonksiyonel tanımınız 'F (X) = F (X) F (X)' olmalıdır. Gerçi ifade etmek için güzel bir yol.
Gerard ONeill

26

Kısacası REST, fiiller üzerindeki isimleri vurgular. API'niz daha karmaşık hale geldikçe, daha fazla komut yerine daha fazla şey eklersiniz.


2
Kafamı bu yönde döndürmekte biraz zorlandım. Bu yazı ( lornajane.net/posts/2013/… ), URI'nin yalnızca isimler içermesi için fiilin HTTP isteğinden gelmesi gerektiğini, benim için biraz temizledi
icc97

9

Siz sordunuz :

JSON nesnesini normal $ _POST aracılığıyla kabul etmek ve ardından JSON'da yanıtlamak daha kolay olmaz

REST'teki Wikipedia'dan :

RESTful uygulamaları, seçilen ağ protokolü tarafından sağlanan önceden var olan, iyi tanımlanmış arabirimin ve diğer yerleşik özelliklerin kullanımını en üst düzeye çıkarır ve üstüne yeni uygulamaya özgü özelliklerin eklenmesini en aza indirir

Gördüğüm kadarıyla, bunun genellikle mevcut HTTP fiillerinin kullanımını en üst düzeye çıkararak ve hizmetiniz için olabildiğince güçlü ve açık bir şekilde bir URL şeması tasarlayarak başarıldığına inanıyorum.

Özel veri protokolleri (SOAP veya JSON gibi standart protokollerin üzerine kurulmuş olsalar bile) önerilmez ve REST ideolojisine en iyi uyması için en aza indirilmelidir.

HTTP üzerinden SOAP RPC ise, her uygulama tasarımcısını genellikle HTTP 'POST' fiilinin üzerine yerleştirilmiş yeni ve rastgele bir isim ve fiil kelime dağarcığı (örneğin getUsers (), savePurchaseOrder (...)) tanımlamaya teşvik eder. Bu, HTTP'nin kimlik doğrulama, önbellekleme ve içerik türü anlaşması gibi mevcut özelliklerinin çoğunu göz ardı eder ve uygulama tasarımcısının bu özelliklerin çoğunu yeni kelimeler içinde yeniden icat etmesine neden olabilir.

Üzerinde çalıştığınız gerçek nesneler herhangi bir biçimde olabilir. Fikir, kullanıcının bu kaynakta gerçekleştirmek istediği işlemlerinizi (sorgular, durum yönetimi / mutasyon, silme) ortaya çıkarmak için mümkün olduğunca çok HTTP'yi yeniden kullanmaktır.

Siz sordunuz :

Bir şey mi kaçırıyorum?

REST ve URI sözdizimi / HTTP fiillerinin kendileri hakkında bilmeniz gereken çok şey var. Örneğin, bazı fiiller idempotenttir, diğerleri değildir. Sorunuzda bununla ilgili hiçbir şey görmedim, bu yüzden buna dalmaya çalışmakla uğraşmadım. Diğer yanıtlar ve Wikipedia'nın her ikisi de çok iyi bilgiye sahip.

Ayrıca, gerçekten dinlendirici bir API kullanıyorsanız, yararlanabileceğiniz HTTP üzerine kurulmuş çeşitli ağ teknolojileri hakkında öğrenilecek çok şey var. Kimlik doğrulamasıyla başlardım.


8

Veri türünü tanımlamak için uzantı kullanma konusunda. MailChimp API'nin bunu yaptığını fark ettim, ancak bunun iyi bir fikir olduğunu düşünmüyorum.

GET /zzz/cars.json/1

GET /zzz/cars.xml/1

Sesim iyi bir fikir gibi, ama bence "daha eski" yaklaşım daha iyi - HTTP üstbilgilerini kullanmak

GET /xxx/cars/1
Accept: application/json

Ayrıca HTTP üstbilgileri, çapraz veri türü iletişimi için çok daha iyidir (eğer biri ihtiyaç duyarsa)

POST /zzz/cars
Content-Type: application/xml     <--- indicates we sent XML to server
Accept: application/json          <--- indicates we want get data back in JSON format  

4

Bir şey mi kaçırıyorum?

Evet. ;-)

Bu fenomen, tek tip arayüz kısıtlaması nedeniyle mevcuttur . REST, tekerleği yeniden icat etmek yerine mevcut standartları kullanmayı sever. HTTP standardının zaten çok ölçeklenebilir olduğu kanıtlanmıştır (web bir süredir çalışmaktadır). Neden kırık olmayan bir şeyi düzeltmeliyiz ?!

Not: İstemcileri hizmetten ayırmak istiyorsanız, tek biçimli arabirim kısıtlaması önemlidir. Sınıfları birbirinden ayırmak için sınıflar tanımlamaya benzer. Ofc. burada tek tip arayüz HTTP , MIME türleri , URI , RDF , bağlantılı veri sözcükleri , hidra sözcükleri , vb . standartlardan oluşur.


2

İyi Semantik programlamada önemlidir.

GET / POST dışında daha fazla yöntem kullanmak faydalı olacaktır çünkü kodunuzun okunabilirliğini artıracak ve bakımını kolaylaştıracaktır.

Neden?

Çünkü GET'in API'nizden veri alacağını biliyorsunuz. POST'un sisteminize yeni veriler ekleyeceğini biliyorsunuz. PUT'un güncelleme yapacağını biliyorsunuz. DELETE, vb. Satırları siler,

Normalde benim RESTFUL Web Services benim yöntemle aynı şey adlı bir işlev geri çağırma var yapılandırmak.

Ben PHP kullanın, bu yüzden function_exists kullanın (Bence denir). İşlev mevcut değilse, bir 405 (İZİN VERİLMEDİ YÖNTEM) atarım.


2

Bill Venners: "Neden REST Başarısız Oldu" başlıklı blog yazınızda , dört HTTP fiiline (GET, POST, PUT ve DELETE) ihtiyacımız olduğunu söylediniz ve neden tarayıcı satıcılarının yalnızca GET ve POST'a ihtiyacımız olduğunu duydunuz. Neden yeterince GET ve POST değilsiniz?

Elliotte Rusty Harold: HTTP'de dört temel yöntem vardır: GET, POST, PUT ve DELETE. GET çoğu zaman kullanılır. Herhangi bir yan etkiye neden olmayan güvenli herhangi bir şey için kullanılır. GET, bir proxy sunucusu üzerinden yer imi eklenebilir, önbelleğe alınabilir, bağlantı kurulabilir. Çok güçlü bir işlem, çok kullanışlı bir işlem.

Buna karşılık POST belki de en güçlü işlemdir. Her şeyi yapabilir. Ne olabileceğine dair herhangi bir sınırlama yoktur ve sonuç olarak, ona çok dikkat etmelisiniz. Yer işareti koymazsınız. Önbelleğe almazsınız. Önceden getirmiyorsunuz. Kullanıcıya sormadan POST ile hiçbir şey yapmazsınız. Bunu yapmak ister misin? Kullanıcı düğmeye basarsa, bazı içeriği POST yapabilirsiniz. Ancak bir sayfadaki tüm düğmelere bakmayacak ve rastgele basmaya başlamayacaksınız. Buna karşılık, tarayıcılar sayfadaki tüm bağlantılara bakıp bunları önceden getirebilir veya bir sonraki adımın izlenmesi en muhtemel olduğunu düşündüklerini önceden getirebilir. Aslında bazı tarayıcılar ve Firefox eklentileri ve diğer çeşitli araçlar bunu bir noktada yapmaya çalıştı.

PUT ve DELETE, GET ve POST arasında ortadadır. PUT veya DELETE ve POST arasındaki fark, PUT ve DELETE öğelerinin * idempotent olması, ancak POST olmamasıdır. Gerekirse PUT ve DELETE tekrarlanabilir. Diyelim ki bir siteye yeni bir sayfa yüklemeye çalışıyorsunuz. Adresinde yeni bir sayfa oluşturmak istediğinizi varsayalımHttp://www.example.com/foo.html adresinde varsayalım, böylece içeriğinizi yazarsınız ve o URL'ye koyarsınız. Sunucu, o sayfayı sağladığınız URL'de oluşturur. Şimdi, herhangi bir nedenle ağ bağlantınızın kesildiğini varsayalım. Emin değilsiniz, istek gerçekleşti mi, gelmedi mi? Belki ağ yavaştır. Belki bir proxy sunucusu sorunu vardı. Bu nedenle, tekrar veya tekrar denemek mükemmeldir - istediğiniz kadar. Çünkü aynı dokümanı aynı URL'ye on kez koymak, bir kez koymaktan farklı olmayacaktır. Aynısı DELETE için de geçerlidir. Bir şeyi on kez Silebilirsiniz ve bu bir kez silmekle aynıdır.

Buna karşılık, POST, her seferinde farklı bir şeyin olmasına neden olabilir. Satın al düğmesine basarak bir çevrimiçi mağazayı ziyaret ettiğinizi düşünün. Bu POST isteğini tekrar gönderirseniz, sepetinizdeki her şeyi ikinci kez satın alabilirsiniz. Tekrar gönderirseniz, üçüncü kez satın aldınız. Bu nedenle tarayıcılar, açıkça kullanıcı izni olmadan POST işlemlerini tekrarlamak konusunda çok dikkatli olmak zorundadır, çünkü POST iki kez yaparsanız iki şeyin, üç kez yaparsanız üç şeyin gerçekleşmesine neden olabilir. PUT ve DELETE ile sıfır istek ile bir arasında büyük bir fark vardır, ancak bir istek ile on arasında fark yoktur.

Daha fazla bilgi için lütfen URL'yi ziyaret edin. http://www.artima.com/lejava/articles/why_put_and_delete.html

Güncelleme:

Idempotent yöntemler Idempotent HTTP yöntemi, farklı sonuçlar olmadan birçok kez çağrılabilen bir HTTP yöntemidir. Yöntemin yalnızca bir kez mi yoksa on kez mi çağrılması önemli değildir. Sonuç aynı olmalıdır. Yine, bu sadece sonuç için geçerlidir, kaynağın kendisi için geçerli değildir. Bu, (mevcut) kaynak gösteriminde paylaşılmadığı sürece yine de değiştirilebilir (güncelleme zaman damgası gibi).

Aşağıdaki örnekleri düşünün:

a = 4;

a ++;

İlk örnek idempotent: bu ifadeyi kaç kez uygulasak da, daima 4 olur. İkinci örnek idempotent değildir. Bunu 10 kez yapmak 5 kez koşarken olduğu gibi farklı bir sonuç doğurur. Her iki örnek de a'nın değerini değiştirdiğinden, ikisi de güvenli olmayan yöntemlerdir.


1
Yeni bir sayfa örneği hakkında, güncelleme için PUT olurken POST bu şekilde kullanılmamalıdır? Yeni bir sayfa oluşturmak, her seferinde yeni bir sonuç getiren bir süreçtir, aynı düzenleme her zaman tekrarlanabilir ve her seferinde aynı sonucu ortaya çıkarabilir. Yine de güzel ifade ve açıklama.
Spyryto

0

Temel olarak REST ( wiki ):

  1. İstemci-sunucu mimarisi
  2. Vatansızlık
  3. önbelleğe alınabilirliğini
  4. Katmanlı sistem
  5. Talep üzerine kod (isteğe bağlı)
  6. Düzgün arayüz

REST protokol değil, prensiptir. Farklı urisler ve yöntemler - en iyi uygulamalar olarak adlandırılan biri.

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.