REST API En iyi uygulamalar: Parametreleri nereye koymalı? [kapalı]


348

Bir REST API'sinin parametreleri en az iki şekilde olabilir:

  1. URL yolunun bir parçası olarak (ör. /api/resource/parametervalue )
  2. Bir sorgu argümanı olarak (ie /api/resource?parameter=value )

Buradaki en iyi uygulama nedir? Ne zaman ve ne zaman 2 kullanılacağına dair genel yönergeler var mı?

Gerçek dünya örneği: Twitter, aralıkları belirtmek için sorgu parametrelerini kullanır. ( http://api.twitter.com/1/statuses/home_timeline.json?since_id=12345&max_id=54321)

Bu parametreleri URL yoluna koymak daha iyi bir tasarım olarak kabul edilir mi?

Yanıtlar:


254

Belgelenmiş en iyi uygulamalar varsa, henüz bulamadım. Ancak, parametreleri bir URL'ye nereye koyacağımı belirlerken kullandığım birkaç yönerge aşağıda verilmiştir:

İsteğe bağlı parametrelerin sorgu dizesine yerleştirilmesi daha kolay olma eğilimindedir.

Parametre değeri mevcut bir kaynağa karşılık gelmediğinde 404 hatası döndürmek istiyorsanız, bir yol segmenti parametresine yönelirim. ör. /customer/232232 geçerli bir müşteri kimliği değil.

Ancak boş bir liste döndürmek istiyorsanız, parametre bulunmadığında sorgu dizesi parametrelerini kullanmanızı öneririm. Örneğin/contacts?name=dave

Bir parametre URI alanınızın tüm alt ağacını etkiliyorsa, bir yol parçası kullanın. örneğin bir dil parametresine /en/document/foo.txt karşı/document/foo.txt?language=en

Benzersiz tanımlayıcıların bir sorgu parametresi yerine bir yol segmentinde olmasını tercih ederim.

URI'ları resmi kurallarında Spec bu RFC bulunur burada . Burada ayrıca URI'leri parametreleştirmek için kuralları tanımlayan çok kullanışlı bir RFC özelliği daha var .


5
Resmi kural URI'leri ve taslak sepc gerçekten yararlı ve ilginçti! :-)
KajMagnus

1
404 hata testi, sorgu parametrelerine, üstbilgilere veya istek gövdesine ait yola bilgi koymaktan kaçınmam için bana çok yardımcı oluyor. Puanınız için teşekkürler!
Kevin Condon

152

Geç cevap, ancak paylaşılan bir şey hakkında ek bilgiler ekleyeceğim, yani bir isteğe birkaç "parametre" türü vardır ve bunu dikkate almalısınız.

  1. Konum Belirleyiciler - Örn. Kimlikler veya işlem / görünüm gibi kaynak tanımlayıcıları
  2. Filtreler - Örneğin, sonuç kümesini arama, sıralama veya daraltma sağlayan parametreler.
  3. Durum - Örn. Oturum tanımlama, api anahtarları, whatevs.
  4. İçerik - Örn. Saklanacak veriler.

Şimdi bu parametrelerin gidebileceği farklı yerlere bakalım.

  1. Üstbilgiler ve çerezler isteyin
  2. URL sorgu dizesi ("GET" değişkenleri)
  3. URL yolları
  4. Gövde sorgu dizesi / çok parçalı ("POST" değişkenleri)

Genel olarak, ne tür bir durum bilgisine bağlı olarak Durum'un başlıklarda veya çerezlerde ayarlanmasını istersiniz. Sanırım hepimiz bu konuda hemfikiriz. Gerekirse özel http üstbilgileri (X-My-Header) kullanın.

Benzer şekilde, İçerik'in sorgu gövdesi olarak veya http çok parçalı ve / veya JSON içeriği olarak istek gövdesinde ait olması gereken tek bir yeri vardır. Bu, size içerik gönderdiğinde sunucudan aldıklarınızla tutarlıdır. Bu yüzden kaba olmamalı ve farklı yapmalısın.

"İd = 5" veya "action = refresh" veya "page = 2" gibi konum belirleyiciler, mysite.com/article/5/page=2her bir parçanın ne anlama geldiğini kısmen bildiğiniz gibi bir URL yolu olarak anlamlı olur (makale ve 5 açıkça bana id 5 ile tip makale veri almak anlamına gelir ve ek parametreler URI bir parçası olarak belirtilir. Bunlar şeklinde olabilir page=2veya page/2URI'da belirli bir noktadan sonra "klasörlerin" eşleştirilmiş anahtar / değer çiftleri olduğunu bilirseniz.

Filtreler her zaman sorgu dizesine gider, çünkü doğru verileri bulmanın bir parçası olsalar da, Konumlandırıcıların tek başına döndürdüklerinin alt kümesini veya değişikliklerini döndürmek için yalnızca oradadırlar. mysite.com/article/?query=Obama(Altküme) içindeki arama bir filtredir, yani /article/5?order=backwards(değiştirilme). Sadece ne denildiğini değil, ne yaptığını düşünün!

"Görünüm" çıktı biçimini belirlerse, o zaman bir filtre ( mysite.com/article/5?view=pdf) olur, çünkü istediğimiz kaynağa odaklanmak yerine bulunan kaynağın bir değişikliğini döndürür. Bunun yerine makalenin hangi kısmını göreceğimize karar verirse ( mysite.com/article/5/view=summary) bir konumlandırıcıdır.

Unutmayın, bir dizi kaynağı daraltmak filtreliyor. Bir kaynağın içinde belirli bir şeyin yerini bulmak ... duh. Alt küme filtrelemesi, istediğiniz sayıda sonuç verebilir (0 bile). Yer belirleme her zaman bir şeyin belirli bir örneğini bulur (varsa). Modifikasyon filtreleme, değiştirilen hariç, konumlandırıcı ile aynı verileri döndürür (böyle bir modifikasyona izin veriliyorsa).

Umarım bu, insanların nereye koyacakları konusunda kaybolurlarsa bazı eureka anları vermelerine yardımcı oldu!


2
Neden idfiltre yok? Kaynağın bir alt kümesini döndürür
Jonathan.

13
@Jonathan. hayır belirli bir kaynağı, yani makale numarasını 5 döndürür. Bir filtre, her zaman bir kaynak koleksiyonundaki aramayı daraltmanın bir yoludur. Sadece belirli bir kaynak istiyorsanız, bunu elde etmek için belirlenmiş bir yol olmalıdır. Filtreleme, birden fazla kaynak döndürme olasılığınız olduğu anlamına gelir. Kimlik bir filtre değildir, kesin bir tek kaynaktır. Bir ARALIK KİMLİĞİNİZ varsa, aralıkta yalnızca bir kimlik olsa bile bir filtre olur. Filtre aynı zamanda kaynak türlerini de içeriyorsa, yalnızca makaleyi değil, 5 numaralı tüm kaynakları döndürür.
Tor Valamo

1
@Jonathan .: DarrelMiller'in de belirttiği gibi, bilinmeyen bir kimlik olması durumunda nesne / id'deki bir isteğin 404 olarak dönmesini beklerken, nesne? İd = id öğesinin geri dönüp listeyi boşaltmasını beklersiniz. Ayrıca, her tür filtreleme / alt kümenin bir liste döndürmesi gerektiğini düşünürüm.
njzk2

1
Sayfalar zordur, çünkü dediğiniz gibi bir kaynağın filtresi (sayfa koleksiyonu) olabilir, ancak aynı zamanda o koleksiyon içindeki belirli bir kaynaktır. Ben her zaman filtre değil, konumlandırıcı tarafından bir makale sayfası rica ediyorum. Bununla birlikte, sayfa, bir kullanıcı listesi gibi, bir şey listesinin filtresi olabilir. Ama sonra sayfa doğal olarak bir sınırlayıcı, yani "öğeden başla (page-1)*perpageve perpageöğeleri göster". Bir filtre olarak kullanmak doğru, ancak farklı nedenlerle. "Sayfa" olarak adlandırmak teknik olarak yanlıştır. Daha semantik olarak doğru "kimden" veya "startAt" demek olacaktır
Tor Valamo

1
(devam) "Sayfa" nın anlamsal anlamı, değişmeyen belirli bir kaynak olmasıdır. Fiziksel baskıdan gelir. Hiç kitabımız veya basılı materyalimiz olmasaydı, "sayfa" gerçekten bir kelime olmazdı. "Sayfalara" bölünmüş dinamik bir öğe listeniz varsa, gerçekten sayısal, alfabetik veya hatta öğeye özgü belirli bir başlangıç ​​noktası ve "sayfa başına kaç" filtre sağlamanız gerekir. Listenizdeki bir şeye başvurmak istersem, ayrıntılar istiyorum. Ayrıca sayfa 5'e gitmek istemiyorum, ancak şimdi dahili perpageolanı 20 yerine 50 olarak değiştirdiğinizi fark etmek istemiyorum
Tor Valamo

21

Bir tasarıma bağlıdır. HTTP üzerinden REST'teki URI'ler için hiçbir kural yoktur (asıl mesele benzersiz olmalarıdır). Genellikle lezzet ve sezgi meselesine gelir ...

Aşağıdaki yaklaşımı benimsiyorum:

  • url yol öğesi: Kaynak ve yol öğesi, bir dizin geçişi ve bir alt kaynak (ör. / items / {id}, / users / items) oluşturur. Emin olmadığınızda meslektaşlarınıza sormaya devam edip etmediklerini ve "başka bir dizinde" düşündüklerini düşünüyorsanız, büyük olasılıkla yol öğesi doğru seçimdir.
  • url parametresi: gerçekten bir geçiş olmadığında (birden fazla sorgu parametresine sahip arama kaynakları bunun için çok güzel bir örnektir)

1
Aslında bir URI'nin nasıl görünmesi gerektiği konusunda oldukça açık kurallar ve bunları RESTful URI'lara nasıl uygulayacağınız konusunda çok az belirsizlik vardır.
DanMan

18

IMO parametreleri sorgu argümanları olarak daha iyi olmalıdır. URL kaynağı tanımlamak için kullanılırken, eklenen sorgu parametreleri kaynağın hangi kısmını, kaynağın sahip olması gereken herhangi bir durumu vb. Belirtmek için kullanılır.


7
Aslında, hem yol hem de sorgu kaynağı tanımlamak için bir arada kullanılır. Bu RFC 3986http://labs.apache.org/webarch/uri/rfc/rfc3986.html#query
Darrel Miller

@DarrelMiller Bu eski bir yazı olduğunu biliyorum ama sorgu parametreleri de kaynağı tanımlamak için kullanılan gerçeği hakkında daha fazla bilgi edinmek istiyorum. Sağladığınız bağlantı artık öldü. RFC3986'ya baktım ama bu gerçeği nasıl çıkardığınızı göremiyorum. Ayrıca, tanım gereği, tanımlayıcı parametreler isteğe bağlı olmamalıdır, bu nedenle tanımlama için sorgu parametrelerini kullanmak uygun görünmez.
Mickael Marrache

@MickaelMarrache Bölüm 3.4'teki
Darrel Miller

2
@DarrelMiller Teşekkürler! Benim sorum genellikle aracı HTTP bileşenlerinin bir sorgu dizesi içeren isteklerin yanıtlarını önbelleğe almaması gerçeğinden kaynaklanmaktadır. Bu nedenle, sorgu parametrelerinin, bir kaynağı benzersiz bir şekilde tanımlamamak için bazı kriterlere göre arama kaynaklarına daha uygun olduğu görülmektedir.
Mickael Marrache

17

REST Uygulaması uyarınca,

1) Yol değişkenleri kaynaklar üzerinde doğrudan eylem için kullanılır, örneğin bir kişi veya şarkı gibi.
GET etc / api / resource / {songid} veya
GET etc / api / resource / {contactid} ilgili verileri döndürür.

2) Sorgu izinleri / bağımsız değişken , örneğin bir şarkının meta verileri, GET / api / resource / {songid}? Metadata = türler gibi doğrudan kaynaklarda kullanılır.


5
Aslında bir REST standardı yoktur . Wikipedia Başına : SOAP tabanlı web hizmetlerinden farklı olarak, RESTful web API'leri için "resmi" bir standart yoktur. [14] Bunun nedeni, REST'in bir protokol olan SOAP'ın aksine mimari bir stil olmasıdır. REST bir standart olmasa da, Web gibi RESTful bir uygulama HTTP, URI, XML, vb. Standartları kullanabilir
DavidRR

İki yaklaşımı sevmiyorum. / Api / türler? Songid = 123 veya / api / şarkılar / {song-id} / türler tercih ederim
Bart Calixto

1
@Bart, Satish, aslında tercihiniz olarak bahsettiğiniz yoldaki Değişkenlere atıfta bulunuyordu. Ancak, türler aslında şarkı verileri / kaynağının bir alanı değil, meta veri ise, o zaman daha fazla duyarlılık görebiliyordum. üzerinde bir sorgu dizesi kullanarak ..
Brett Caswell

@BrettCaswell anladı! işaret ettiğiniz için teşekkürler. gerçekten takdir ediyorum!
Bart Calixto

16

Verilerinizi evren-kaynak-konum belirleyicisinin sağladığı "bağlam" a göre paketleyin ve POST yapın, bu da konumlandırıcı adına # 1 anlamına gelir.

# 2 ile ilgili sınırlamalara dikkat edin. POST'ları # 1'e tercih ederim.

not: için sınırlamalar tartışılmıştır

POST girişi POST parametre içeriği için maksimum boyut var mı?

GET in Bir GET isteğinin uzunluğu için bir sınır var mı? ve _GET URL parametrelerinin Maks boyut

ps bu sınırlar istemci yeteneklerine (tarayıcı) ve sunucuya (yapılandırmaya) dayanır.


eklenti: esprili yolların sürümleri olabilir (üstbilgilerle ayırt edilir), böylece restify'da yazdığınız geri kalan tam (api) kodunu tüketen kodu değiştirmeye gerek kalmadan gelişmiş işlevsellik sağlar ->
Sürümlü

5

Göre URI standardı yolu hiyerarşik parametreler için ve sorgu hiyerarşik olmayan parametrelerin içindir. Ofc. sizin için hiyerarşik olan çok öznel olabilir.

Aynı kaynağa birden fazla URI'nin atandığı durumlarda, tanımlama için gerekli parametreleri yola ve gösterimi oluşturmak için gerekli parametreleri - sorguya koymak istiyorum. (Benim için bu şekilde yönlendirmek daha kolay.)

Örneğin:

  • /users/123 ve /users/123?fields="name, age"
  • /users ve /users?name="John"&age=30

Harita indirgemek için aşağıdaki yaklaşımları kullanmayı seviyorum:

  • /users?name="John"&age=30
  • /users/name:John/age:30

Bu yüzden URI'lerinizi nasıl oluşturduğunuz tamamen size (ve sunucu tarafı yönlendiricinize) bağlıdır.

not: Sadece bu parametrelerden sorgu parametreleri bahsediyoruz. Yani gerçekten yaptığınız basit bir sorgu dili tanımlamak. Karmaşık sorgular ile (ve, veya daha büyük, vb. Gibi işleçler içerir) zaten var olan bir sorgu dilini kullanmanızı öneririm. Yetenekleri URI şablonları çok sınırlıdır ...


4

Genellikle istemci tarafında bir programcı olarak, sorgu bağımsız değişkenini tercih ederim. Ayrıca, benim için, URL yolunu parametrelerden ayırır, netlik kazandırır ve daha fazla genişletilebilirlik sunar. Aynı zamanda URL / URI binası ile parametre oluşturucu arasında ayrı bir mantığa sahip olmamı sağlıyor.

Bir çeşit ağaç varsa, manuel aldana'nın diğer seçenek hakkında söylediklerini beğeniyorum. Kullanıcıya özel parçaların bu şekilde tizlendiğini görebiliyorum.


4

Zor ve hızlı kurallar yoktur, ancak kullanmayı düşündüğüm tamamen kavramsal bir bakış açısından başparmak kuralı kısaca şöyle özetlenebilir: bir URI yolu (tanım gereği) bir kaynağı temsil eder ve sorgu parametreleri esas olarak bu kaynakta değiştiricilerdir . Şimdiye kadar muhtemel bir REST API ile ... değil moral verdi kullanmakta tek kaynağın üzerine etki eden başlıca yöntemleri var GET, PUTve DELETE. Bu nedenle, bir şeyin yolda mı yoksa parametre olarak mı temsil edileceği, bu yöntemlerin söz konusu temsil için anlamlı olup olmadığına indirgenebilir. PUTBu yolda makul bir şey yapar mıydınız ve bunu yapmak anlamsal olarak sağlam mı olur? Tabii ki PUThemen hemen her yerde bir şey olabilir ve bununla başa çıkmak için arka ucu bükebilirsiniz, ancakPUTgerçek kaynağın temsili anlamına gelir ve bunun gereksiz yere bağlamsallaştırılmış bir versiyonu değildir. Koleksiyonlar için de aynı şey yapılabilir POST. Belirli bir koleksiyona eklemek isterseniz bunun ne anlama geldiği bir URL olurdu POST.

Bu bazı gri alanlar bırakıyor, çünkü bazı yollar ebeveyn kaynaklarının çocuklarına ne ölçüde bir miktar isteğe bağlı ve bunların kullanımına bağlı olduğunu gösterebilir. Bunun çizdiği tek sabit satır, altta yatan bir kaynağa sahip olmayacağı için herhangi bir geçişli gösterimin bir sorgu parametresi kullanılarak yapılması gerektiğidir.

Orijinal soruda (Twitter'ın API'sı) verilen gerçek dünya örneğine yanıt olarak, parametreler, kaynakların durumuna (hiyerarşi yerine) filtre uygulayan geçişli bir sorguyu temsil eder. Bu özel örnekte, bu kısıtlamalar tarafından temsil edilen koleksiyona eklemek tamamen mantıksız olacaktır ve ayrıca bu sorgu, bir nesne grafiği açısından herhangi bir anlam ifade edecek bir yol olarak gösterilemeyecektir.

Bu tür kaynak odaklı bakış açısının benimsenmesi, doğrudan etki alanı modelinizin nesne grafiğiyle eşleştirilebilir ve API'nizin mantığını, her şeyin çok temiz bir şekilde çalıştığı noktaya ve netleştiğinde oldukça kendi kendini belgeleyen bir şekilde yönlendirebilir. Kavram, normalde uymayan bir veri modeline (yani bir RDBMS) eşlenen geleneksel URL yönlendirmesini kullanan sistemlerden uzaklaşarak da daha net hale getirilebilir. Apache Sling kesinlikle başlamak için iyi bir yer olacaktır. Zope gibi bir sistemde nesne geçişi gönderme kavramı da daha net bir analog sağlar.


4

İşte benim görüşüm.

Sorgu parametreleri bir isteğe meta veri olarak kullanılır. Varolan bir kaynak çağrısına filtre veya değiştirici görevi görürler.

Misal:

/calendar/2014-08-08/events

o gün için takvim etkinlikleri vermelidir.

Belirli bir kategori için etkinlik istiyorsanız

/calendar/2014-08-08/events?category=appointments

veya 30 dakikadan uzun etkinliklere ihtiyacınız varsa

/calendar/2014-08-08/events?duration=30

Bir turnusol testi, isteğin bir sorgu parametresi olmadan da sunulup sunulmayacağını kontrol etmek olacaktır.


2

Ben genellikle # 2, bir sorgu argüman (yani / api / resource? Parametre = değer) doğru eğilimindedir.

Üçüncü seçenek aslında = value parametresini gövdeye kaydetmektir.

Bunun nedeni, çok parametreli kaynaklar için daha iyi çalışması ve gelecekteki kullanım için daha uzatılabilir olmasıdır.

Hangisini seçerseniz seçin, sadece bir tane seçtiğinizden emin olun, karıştırmayın ve eşleştirmeyin. Bu kafa karıştırıcı bir API'ye götürür.


2

Bu konunun bir "boyutu" hariç tutulmuştur, ancak bu çok önemlidir: "en iyi uygulamaların" REST yetenekleri ile uyguladığımız veya artırdığımız plaform ile anlaşması gereken zamanlar vardır.

Pratik örnek:

Günümüzde birçok web uygulaması MVC (Model, View, Controller) mimarisini uygulamaktadır. Belirli bir standart yolun sağlandığını varsayarlar, bu web uygulamaları bir "SEO URL'lerini Etkinleştir" seçeneği ile geldiğinde daha da fazladır.

Oldukça ünlü bir web uygulamasından bahsetmek için: OpenCart e-ticaret mağazası. Yönetici "SEO URL'lerini" etkinleştirdiğinde, söz konusu URL'lerin aşağıdaki gibi oldukça standart bir MVC biçiminde gelmesini bekler:

http://www.domain.tld/special-offers/list-all?limit=25

Nerede

  • special-offers URL'yi işleyecek MVC denetleyicisidir (özel teklifler sayfasını gösterir)

  • list-alldenetleyicinin arayacağı eylem veya işlev adıdır. (*)

  • limit = 25, her sayfada 25 öğenin gösterileceğini belirten bir seçenektir.

(*) list-allnetlik için kullandığım kurgusal bir işlev adıdır. Gerçekte, OpenCart ve çoğu MVC çerçevesi index, kullanıcı varsayılan bir eylemin gerçekleştirilmesini istediğinde çağrılan varsayılan, zımni (ve genellikle URL'de atlanır) işlevine sahiptir. Yani gerçek dünya URL'si:

http://www.domain.tld/special-offers?limit=25

Yukarıdakilere benzer şimdi oldukça standart bir uygulama veya frameworkd yapısı ile, genellikle bunun için optimize edilmiş, bunun için URL'leri yeniden yazan bir web sunucusu alırsınız (gerçek "SEOed olmayan URL":) olacaktır http://www.domain.tld/index.php?route=special-offers/list-all&limit=25.

Bu nedenle, geliştirici olarak, sistem yöneticisi değilseniz, bir Apache / NGinx yeniden yazma yapılandırmasını (ikincisi kötü olabilir!) üzerinde.

Bu nedenle, REST API'niz, hem onunla tutarlılık hem de kolaylık / hız (ve dolayısıyla bütçe tasarrufu) için atıfta bulunulan web uygulamasının standartlarını izleyerek çok daha iyi olur.

Yukarıdaki pratik örneğe geri dönmek için, tutarlı bir REST API'si aşağıdaki URL'lere sahip bir şey olacaktır:

http://www.domain.tld/api/special-offers-list?from=15&limit=25

veya (SEO dışı URL'ler)

http://www.domain.tld/index.php?route=api/special-offers-list?from=15&limit=25

"oluşan yollar" argümanları ve "sorgu oluşturuldu" argümanlarının bir karışımı ile.



0

Çok ilginç bir soru.

Her ikisini de kullanabilirsiniz, bu konuyla ilgili katı bir kural yoktur, ancak URI yolu değişkenlerini kullanmanın bazı avantajları vardır:

  • Önbellek : İnternetteki web önbellek hizmetlerinin çoğu, sorgu parametreleri içerdiğinde GET isteğini önbelleğe almaz. Bunu yaparlar çünkü sunucudaki verileri değiştirmek için GET isteklerini kullanan çok sayıda RPC sistemi vardır (başarısız! Get! Güvenli bir yöntem olmalı)

Ancak yol değişkenleri kullanıyorsanız, bu hizmetlerin tümü GET isteklerinizi önbelleğe alabilir.

  • Hiyerarşi : Yol değişkenleri hiyerarşiyi temsil edebilir: / Şehir / Sokak / Yer

Kullanıcıya verilerin yapısı hakkında daha fazla bilgi verir.

Ancak verilerinizde herhangi bir hiyerarşi ilişkisi yoksa, virgül veya noktalı virgül kullanarak yine de Yol değişkenlerini kullanabilirsiniz:

/ Şehir / boylam, enlem

Kural olarak, parametrelerin sıralaması önemli olduğunda virgül kullanın, sıralama önemli olmadığında noktalı virgül kullanın:

/ IconGenerator / kırmızı, mavi, yeşil

Bu nedenlerin dışında, sorgu dizesi değişkenlerini kullanmanın çok yaygın olduğu bazı durumlar vardır:

  • HTML form değişkenlerini otomatik olarak URI'ye koymak için tarayıcıya ihtiyacınız olduğunda
  • Algoritma ile uğraşırken. Örneğin, google motoru sorgu dizeleri kullanır:

http: // www.google.com/search?q=rest

Özetlemek gerekirse, bu yöntemlerden birini kullanmanın güçlü bir nedeni yoktur, ancak mümkün olduğunda URI değişkenlerini kullanın.

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.