URL sorgu parametreleri ile HTTP POST - iyi bir fikir mi değil mi? [kapalı]


451

Ben HTTP üzerinden gitmek için bir API tasarlıyorum ve HTTP POST komutunu kullanarak merak ediyorum, ama sadece URL sorgu parametreleri ve hiçbir istek gövdesi ile gitmek için iyi bir yoldur.

hususlar:

  • "İyi Web tasarımı", POST yoluyla idempotent olmayan eylemlerin gönderilmesini gerektirir. Bu idempotent olmayan bir eylemdir.
  • URL'de istek parametreleri bulunduğunda bu uygulamayı geliştirmek ve hatalarını ayıklamak daha kolaydır.
  • API yaygın kullanıma yönelik değildir.
  • Görünüşe göre, hiçbir gövdeden bir POST isteği yapmak biraz daha fazla iş gerektirmeyecektir, örneğin bir Content-Length: 0başlık açıkça eklenmelidir.
  • Bana öyle geliyor ki, gövdesi olmayan bir POST, çoğu geliştiricinin ve HTTP çerçevesinin beklentilerine karşı biraz karşıdır.

İstek gövdesi yerine, URL sorgusu üzerinden bir POST isteğinde parametre göndermenin başka tuzakları veya avantajları var mı?

Düzenleme: Bu göz önünde bulundurulmasının nedeni, operasyonlar idempotent değildir ve alma dışında yan etkileri olmasıdır. HTTP spesifikasyonuna bakın :

Özellikle, GET ve HEAD yöntemlerinin geri alım dışında bir işlem yapmanın önemine sahip OLMAMASI gerektiği anlaşılmıştır. Bu yöntemler "güvenli" olarak değerlendirilmelidir. Bu, kullanıcı aracılarının POST, PUT ve DELETE gibi diğer yöntemleri özel bir şekilde temsil etmesini sağlar, böylece kullanıcı muhtemelen güvenli olmayan bir eylemin istendiğinden haberdar edilir.

...

Yöntemler "idempotence" özelliğine de sahip olabilir (hata veya son kullanma sorunlarının yanı sıra) N> 0 özdeş isteklerin yan etkileri tek bir istekle aynıdır. GET, HEAD, PUT ve DELETE yöntemleri bu özelliği paylaşır. Ayrıca, OPTIONS ve TRACE yöntemlerinin yan etkileri OLMAMALIDIR ve bu nedenle doğası gereği idempotenttir.


11
Vücutta veri sağlamayacaksanız neden POST'u kullanıyorsunuz?
Sunny Milenov

114
Çünkü operasyon idempotent değil.
Steven Huwig

20
@Jared, 2.5 yıl önce bu soruda "REST" kelimesinin görünmediğine dikkat edin. :) İdempotence ile ilgili HTTP spesifikasyonu, ayın lezzetinin web hizmetleri için ne olduğuna bakılmaksızın uygulanır. Neyse ki, bu API'nın proxy için tasarlandığı sistem yine de eski haline getirildi.
Steven Huwig

5
Çünkü sunucu günlükleri POST parametrelerini kaydetmez, ancak sorgu dizelerini kaydeder. İstek dizisini tarayıcıda kullanmadan çalıştırmak ve ardından geri izlemeye bakmak, tıklatmaktan çok daha kolaydır. Ayrıca API tarayıcıdan sunucuya değil, sunucudan sunucuya idi. En önemlisi, her şey zaten konserve edildi. :)
Steven Huwig

13
İdempotent'in ne anlama geldiğini bilmeyen herkes için: | restapitutorial.com/lessons/idempotency.html
Christopher Grigg

Yanıtlar:


260

Eyleminiz idempotent değilse, kullanmanız GEREKİRPOST . Eğer yapmazsan, sadece hattan sorun istiyorsun. GET, PUTVe DELETEyöntemler vardır gerekli İdempotent olması. İstemci, GEThizmetiniz için olası her isteği önceden getiriyorsa uygulamanızda ne olacağını hayal edin - bu, istemcinin göreceği yan etkilere neden olursa, bir sorun var demektir.

Ben POSTbir sorgu dizesi ile ama bir gövde olmadan gönderme garip görünüyor, ama bazı durumlarda uygun olabileceğini düşünüyorum.

Bir URL'nin sorgu bölümünü, geçerli isteğin kapsamını sınırlamak için kaynağa bir komut olarak düşünün. Tipik olarak, sorgu dizeleri bir GETisteği (gibi ?page=1&sort=title) sıralamak veya filtrelemek için kullanılır, ancak bir POSTkapsamı (belki de gibi ?action=delete&id=5) sınırlamak için de mantıklı olduğunu varsayalım .


4
Bu cevabı bu özel durum için seçtim, ancak bence R. Bemrose'un argümanı herkese açık API'lar için zorlayıcı.
Steven Huwig

4
Cevabının kesinlikle doğru olduğunu düşünmüyorum. HTML sayfası istemciye gönderilirken form postanızın URL parametrelerini biliyorsanız, bu URL parametrelerini formun action özelliğine bağlayabilirsiniz, aksi takdirde JavaScript form gönderildiğinde URL parametrelerini ayarlayabilir.
Don McCaughey

3
bir xml dosyasının sorgu parametrelerine sahip bir url'ye gönderilmesine ne dersiniz? mümkün mü?
OpenCoderX

3
Başka bir örnek: yanıt verisi http öğesinde olabilirken, yanıtın istenen biçimi sorgu parametresinde ( /action?response_format=json)
rds

4
+1 bugün bir şeyler öğrendi. Delete, idempotent olma özelliğine sahiptir. Nesne gerçekten silinirse, sunucu aynı duruma sahip olacak, ancak yanıt farklı olacak şekilde 404 bulunamadı. İnek Resmine
Bakın

131

Herkes haklı: idempotent olmayan talepler için POST'a sadık kalın.

Hem bir URI sorgu dizesi hem de istek içeriği kullanmaya ne dersiniz? Peki geçerli HTTP (not 1'e bakınız), neden olmasın ?!

Ayrıca tamamen mantıklıdır: Sorgu dizesi parçaları da dahil olmak üzere URL'ler kaynakları bulmak içindir . HTTP yöntemi fiilleri (POST - ve isteğe bağlı istek içeriği) eylemleri veya kaynaklarla ne yapılacağını belirtmek içindir . Bunlar dik kaygılar olmalıdır. (Ancak, ContentType = application / x-www-form-urlencoded özel durumu için güzel dikey endişeler değildir, aşağıdaki not 2'ye bakın.)

Not 1: HTTP belirtimi (1.1), sorgu parametrelerinin ve içeriğinin POST veya PUT isteklerini kabul eden bir HTTP sunucusu için birbirini dışladığını belirtmez. Yani herhangi bir sunucu her ikisini de kabul etmekte özgürdür. Yani sunucuyu yazarsanız, her ikisini de kabul etmeyi durduracak hiçbir şey yoktur (belki esnek olmayan bir çerçeve hariç). Genellikle, sunucu sorgu dizelerini istediği kurallara göre yorumlayabilir. Hatta onları İçerik Türü gibi diğer başlıklara atıfta bulunan Not 2'ye götüren koşullu mantıkla da yorumlayabilir:

Not 2: Bir web tarayıcısı , kullanıcıların web uygulamanıza erişmesinin birincil yoluysa ve application / x-www-form-urlencoded , yayınladıkları İçerik Türü ise, o İçerik Türü için kuralları izlemeniz gerekir . Ve application / x-www-form-urlencoded için kurallar çok daha spesifiktir (ve açıkçası, olağandışı): bu durumda URI'yi bir kaynak konumu olarak değil, bir parametre kümesi olarak yorumlamanız gerekir. [Bu Powerlord'un kullandığı aynı kullanışlılık noktasıdır; sunucunuza içerik göndermek için web formlarını kullanmanın zor olabileceğini unutmayın. Sadece biraz farklı açıkladım.]

Not 3: Sorgu dizeleri orijinal olarak ne içindir? RFC 3986, HTTP sorgu dizelerini, kaynağı bulmanın hiyerarşik olmayan bir yolu olarak çalışan bir URI parçası olarak tanımlar.

Bu soruyu soran okuyucuların iyi RESTful mimarisinin ne olduğunu sormak istemeleri durumunda: RESTful mimari modeli URI şemalarının belirli bir şekilde çalışmasını gerektirmez. RESTful mimarisi, kaynakların önbelleğe alınabilirliği, kaynakların kendilerinin tasarımı (davranışları, yetenekleri ve temsili) ve idempotence'in karşılanıp karşılanmadığı gibi sistemin diğer özellikleriyle ilgilidir. Başka bir deyişle, HTTP protokolü ve HTTP yöntemi fiil kümesiyle son derece uyumlu bir tasarım elde etmek. :-) (Diğer bir deyişle, RESTful mimari kaynakları nasıl çok presciptive değildir bulunan .)

Son not: bazen sorgu parametreleri, kaynakları bulmayan veya içeriği kodlamayan diğer şeyler için kullanılır. Hiç 'PUT = true' veya 'POST = true' gibi bir sorgu parametresi gördünüz mü? Bunlar, PUT ve POST yöntemlerini kullanmanıza izin vermeyen tarayıcılar için geçici çözümlerdir. Bu tür parametreler (tel üzerinde) URL sorgu dizesinin bir parçası olarak görülmekle birlikte, onlar ruhu içinde URL sorgusunun bir parçası olmadığını iddia ediyorum .


66

Sebep mi istiyorsun? Işte bir tane:

Web formu, GET ve POST karışımı kullanan bir sayfaya istek göndermek için kullanılamaz. Formun yöntemini GET olarak ayarlarsanız, tüm parametreler sorgu dizesinde bulunur. Formun yöntemini POST olarak ayarlarsanız, tüm parametreler istek gövdesinde olur.

Kaynak: HTML 4.01 standardı, bölüm 17.13 Form Gönderme


10
Bu iyi bir argüman, ama bence modern tarayıcının Javascript uygulamaları bunu tartışmalı bir nokta haline getiriyor. Yine de düşüneceğim - geleceğe hazır bir şekilde zorlayıcı. Bunun için şimdi bir form kullanmadığım için daha sonra istemeyeceğim anlamına gelmez.
Steven Huwig

9
GET'i POST ile karıştırmak gerçekten kötü bir fikirdir - HTTP'yi çok kırmak ve iyi bir sebep olmaksızın.
aehlke

6
Bu pasaj bağlantı verdiğiniz sayfada görünmüyor
Gareth

40
Doğru, ancak method özelliği yalnızca "form veri kümesi" nin isteğe nasıl dahil edildiğini tanımlar. methodPOST olduğunda, formdaki URI'yi değiştirmekten bahsedilmez action. Ve herhangi bir URI elbette bir sorgu dizesi parçası içerebilir.
Gareth

16
@ Powerlord Bu sadece yanlış. Örn. Eylemiyle bir formu POST olarak ayarlamayı deneyin. /Books?bookCode=1234. Web sunucusu POST form değişkenleri ve bir sorgu dizesi alacaktır.
Jez

9

Programlı bir bakış açısından, müşteri için parametreleri paketliyor ve bunları url'ye ekliyor ve bir GET'e karşı bir POST yürütüyor. Sunucu tarafında, gönderilen baytlar yerine sorgu dizesinden gelen parametreleri değerlendirir. Temel olarak, bir yıkama.

Avantajların / dezavantajların olabileceği yerlerde, belirli istemci platformlarının ağ yığınlarındaki POST ve GET yordamlarıyla nasıl çalıştığı ve web sunucusunun bu isteklerle nasıl başa çıktığı olabilir. Uygulamanıza bağlı olarak, bir yaklaşım diğerinden daha verimli olabilir. Bunu bilmek burada kararınızı yönlendirecektir.

Bununla birlikte, bir programcının bakış açısından, vücuttaki tüm parametrelerle bir POST'ye veya url'deki tüm parametrelerle bir GET'e izin vermeyi ve herhangi bir POST isteği ile url parametrelerini açıkça görmezden gelmeyi tercih ederim. Karışıklığı önler.


8

İçerik yükü POST gövdesi ile sınırlı tutarken URL üzerindeki kaynağı tanımlayan sorgu argümanlarına sahip olmanın hala oldukça RESTful olabileceğini düşünürdüm. Bu, "Ne gönderiyorum?" "Kime gönderiyorum?"


5
Soru REST ile ilgili değildi.
Steven Huwig

3
@ user359996 Tüm HTTP API'leri RESTful değildir. Aslında, aslında olmadığını iddia eden çoğu API. Ayrıca, eğlenceli gerçek, REST de sadece HTTP değil.
Alec Mev

4

DİNLENME kamp biz HTTP fiiller kullanma şeklinizi standardize için kullanabileceği bazı yol gösterici ilkeler vardır. Bu, yaptığınız gibi RESTful API'leri oluştururken yardımcı olur.

Özetle: GET Salt Okunur olmalıdır, yani sunucu durumu üzerinde hiçbir etkisi yoktur. POST, sunucuda bir kaynak oluşturmak için kullanılır. PUT, bir kaynağı güncellemek veya oluşturmak için kullanılır. DELETE bir kaynağı silmek için kullanılır.

Başka bir deyişle, API eyleminiz sunucu durumunu değiştirirse, REST bize POST / PUT / DELETE kullanmanızı sağlar, ancak GET kullanmamamızı önerir.

Kullanıcı aracıları genellikle birden fazla POST yapmanın kötü olduğunu ve buna karşı uyaracağını anlar, çünkü POST'un amacı sunucu durumunu değiştirmek (örn. Kasada mallar için ödeme yapmak) ve muhtemelen bunu iki kez yapmak istemezsiniz!

İstediğiniz sıklıkta yapabileceğiniz bir GET ile karşılaştırın (idempotent).


13
REST kampı, HTTP spesifikasyonunda tanımlandığı gibi HTTP kullanmanız gerektiğini söylüyor. Yani RFC2616 Başka bir şey, hiçbir şey daha az.
Darrel Miller

1
@Darrel Yönlendiren ibm.com/developerworks/webservices/library/ws-restful : REST, geliştiricilerin HTTP yöntemlerini açıkça ve protokol tanımıyla tutarlı bir şekilde kullanmalarını ister. Bu temel REST tasarım ilkesi, oluşturma, okuma, güncelleme ve silme (CRUD) işlemleri ile HTTP yöntemleri arasında bire bir eşleme oluşturur. Bu eşlemeye göre: Sunucuda bir kaynak oluşturmak için POST'u kullanın. Bir kaynağı almak için GET işlevini kullanın. Bir kaynağın durumunu değiştirmek veya güncellemek için PUT kullanın. Bir kaynağı kaldırmak veya silmek için SİL'i kullanın.
saille

5
Üzgünüm ama bu sadece yanlış. REST, düzgün bir arayüze uyum gerektirir. HTTP kullanıyorsanız, bu tekdüzen arayüz kısmen RFC 2616 tarafından tanımlanır. Bu spesifikasyonda, oluşturma, okuma, güncelleme ve silme ile HTTP yöntemleri arasında bire bir eşleme yoktur.
Darrel Miller

3
GUD and DELETE, CRUD'da Okuma ve Silme için oldukça iyi bir haritaya sahiptir, ancak Güncelleme ve Oluşturma için PUT / POST kullanımı basit değildir. Bkz. Stackoverflow.com/questions/630453/put-vs-post-in-rest
dcstraw

5
Bu 6 yıl sonra geriye dönüp baktığımızda ve sorunun yaklaşık 100 bin kez incelendiği göz önüne alındığında, küçük bir güncellemeye koymaya değer olduğunu hissediyorum. Darrel, Fielding'in REST tanımına ( ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm ) göre doğrudur - HTTP fiillerini CRUD ile eşleştirmekten bahsedilmez. IBM'in geliştirici tavsiyesi (yukarıdaki açıklamadaki bağlantı), Fielding'in REST tanımını değil, RESTful API'lerinin uygulanmasındaki yaygın uygulamaları yansıtır.
saille

-13

Kabul ediyorum - verileri yalnızca URL'ye değil, URL'ye geçiriyorsanız bir GET isteği kullanmak daha güvenlidir. Tüm POST + GET konseptiyle ilgili bazı ek görüşler için bu benzer soruya bakın .


17
İşlemin yan etkileri varsa, GET yöntemini kullanmak kesinlikle daha güvenli değildir, çünkü tarayıcı tüm GET'lerin idempotent olduğunu varsayar.
dcstraw

Arama motorları, Google'ın GET isteğiyle tüm bağlantıları güvenli bir şekilde "tıklayacağı", ancak diğer her şeyi atlayacağı için bunu bir kabusta dönüştürür. Masum bir tarayıcının veritabanını yanlışlıkla silebileceği bir hizmet bırakmak o kadar güvenli değildir.
Alejandro
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.