REST API TASARIMI - Farklı parametrelere sahip ancak aynı url modeline sahip REST aracılığıyla bir kaynak alma


92

REST url tasarımıyla ilgili bir sorum var. Burada bazı ilgili gönderiler buldum: Aynı kaynağın farklı RESTful temsilleri ve burada: Farklı alanlara göre GET kaynağına RESTful url, ancak yanıtlar en iyi uygulamaların ne olduğu ve neden olduğu konusunda pek net değil. İşte bir örnek.

"Kullanıcılar" kaynağını temsil eden REST url'lerim var. Kimliği veya e-posta adresi olan bir kullanıcıyı ALABİLİRİM, ancak URL gösterimi her ikisi için de aynı kalır. Birçok blog ve kitapta dolaştığımda, insanların bunu birçok farklı şekilde yaptığını görüyorum. Örneğin

bu uygulamayı bir kitapta ve stackoverflow'da bir yerde okuyun (bağlantıyı tekrar bulamıyorum gibi görünüyor)

GET /users/id={id}
GET /users/email={email}

bu uygulamayı birçok blogda okuyun

GET /users/{id}
GET /users/email/{email}

Sorgu parametreleri normalde url tarafından temsil edilen kaynakların sonuçlarını filtrelemek için kullanılır, ancak bu uygulamanın da kullanıldığını gördüm

GET /users?id={id}
GET /users?email={email}

Sorum şu, tüm bu uygulamalardan hangisi api kullanan geliştiriciler için en mantıklıdır ve neden? REST url tasarımları ve adlandırma kuralları söz konusu olduğunda kesin olarak belirlenmiş hiçbir kural olmadığına inanıyorum, ancak geliştiricilerin apileri daha iyi anlamalarına yardımcı olmak için hangi yolu izlemem gerektiğini bilmek istedim.

Tüm yardımlar takdir edildi!


1
Bunun biraz eski olduğunu biliyorum ama benzer kaynakları ararken bu ve sizin aradığınız soruyla karşılaşıyorum. Sanırım bu tek stackoverflow.com/a/9743414/468327
Joel Berger

Yanıtlar:


104

Tecrübelerime göre, GET /users/{id} GET /users/email/{email}en yaygın yaklaşım budur. Sağlanan idveya ile bir kullanıcı yoksa, yöntemlerin bir 404 Bulunamadı döndürmesini beklerdim email. Ben de görünce şaşırmam GET /users/id/{id}(bence gereksiz olsa da).

Diğer yaklaşımlarla ilgili yorumlar

  1. GET /users/id={id} GET /users/email={email}
    • Bunu gördüğümü sanmıyorum ve görseydim çok kafa karıştırıcı olurdu. Sorgu parametrelerini yol parametreleriyle taklit etmeye çalışıyor gibi.
  2. GET /users?id={id} GET /users?email={email}
    • Filtreleme için sorgu parametrelerini kullanmaktan bahsettiğinizde başınıza çiviyi vurduğunuzu düşünüyorum.
    • Her zamankinden anlamda ile bu kaynağı aramak kılacak hem An idve email(örneğin GET /users?id={id}&email={email})? Değilse, bunun gibi tek bir kaynak yöntemi kullanmazdım.
    • Ben almak için bu yöntemi beklenebilir listesini filtrelemek için İsteğe bağlı sorgu parametreleri ile kullanıcıların, ama beklemek olmaz id, emailya da herhangi bir benzersiz tanımlayıcı parametreleri arasında yer almak. Örneğin: GET /users?status=BANNEDyasaklı kullanıcıların bir listesini döndürebilir.

Check out bu cevabı İlgili bir soru dan.


Giriş için teşekkürler. Aslında haklısın. Görünüşe göre "Jax-rs ile RESTful java" kitabında 1 numarayı okudum ama biraz bağlam dışı. Ancak, stackoverflow ile ilgili sorulardan birinin cevabı olarak okuduğumu çok net bir şekilde hatırlıyorum (meslektaşlarıma da kanıtlamak için bu bağlantıyı bulmaya çok çalıştığımı söylediğimde bana inanın :)) ve # 2 tam olarak benim olduğum şeydi aramak. Tasarımla ilgili bazı geri bildirimler. Teşekkür ederim!
shahshi15

Not: Bunu burada yayınlamak kurala aykırı mı emin değilim ama muhtemelen diğer sorularımdan birine de ışık tutabilirsiniz? Lütfen? :) stackoverflow.com/questions/20508008/…
shahshi15

Sadece artıklık beyanınızla ilgili olarak açıklığa kavuşturmak için /users/id/{id}, bu genişletilmiş işlevselliğe izin verir, yalnızca bir kaynağa birkaç tanımlayıcı (id, guid, name) aracılığıyla erişmeye izin verir. burada
Daniel Dubovski

4
Cevabım, örneğin belirli bir Kullanıcıya atıfta bulunmanın uygun yolunun / users / {id} olacağı şeklinde olacaktır. Kullanıcıları, kullanıcılar için benzersiz tanımlayıcı olmayan belirli bir e-posta adresine göre bulmak istiyorsanız, yapardım / users? Email = {email}, çünkü bu, belirli bir kaynağı kaynağına göre tanımlamak değil, kullanıcı koleksiyonunu filtrelemenin bir yolu / users / {id} olarak tanımlayıcı.
Kevin M

Mükemmel cevap! Başparmakla. DİNLENME Kaynaklarınızın eşleştirmeleri gibi bir şey olmalı bu yüzden adı merkezli olması gerektiği gibi ben yapmak öneriyoruz tek şey API biraz değiştirmek de geçerli: GET /user/1234ve değilGET /users/123
Sammy

38

Buna pragmatik olarak baktığımızda, bir kullanıcı koleksiyonunuz var:

/users   # this returns many

Her kullanıcının özel bir kaynak konumu vardır:

/users/{id}    # this returns one

Ayrıca, kullanıcıları aramak için birçok yolunuz var:

/users?email={email}
/users?name=*bob*

Bunların tümü / users için sorgu parametreleri olduğundan, hepsi 1'in listesi olsa bile listeleri döndürmelidir.

Burada pragmatik RESTful API tasarımı üzerine başka şeylerin yanı sıra burada bahseden bir blog yazısı yazdım: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api


Cevap vinay için teşekkürler. Ancak bunu başka bir açıdan düşünürsek, {email} tıpkı {id} gibi HER ZAMAN bir sonuç geri döndürecektir. Gerçekten arıyorsak, neden e-posta için olduğu gibi? İd = {id} kullanmıyoruz? Tutarlı olmanın bir yolu var mı diye merak ediyordum. Not: stackoverflow için yeni, sadece bir cevap verebileceğimi bilmiyordum. Cevabınız için teşekkürler! Takdir et. Belki bana bu konuda da yardımcı olabilirsiniz: stackoverflow.com/questions/20508008/…
shahshi15

7
API tasarımının "tasarım" yönü burada devreye giriyor. Kaynağınızın özel bir konumu olmalıdır. Konum neresi? Konum kimliğe göre mi? Öyleyse, kimliğe göre "arama" yapmazsınız, kimliğe göre "alırsınız". Ama her şeye göre arama yaparsınız. Tabii ki, burada kesin bir kural yok. Bu sadece bir bakış açısı :)
Vinay Sahni

6
Ayrıca API'nizin bu şekilde daha kararlı olduğunu da iddia ediyorum. Kimliğinizin benzersiz olduğunu gerçekten biliyorsunuz, ancak e-posta adresinden gerçekten emin misiniz? Benzersiz olsa bile, kullanıcı değiştirebileceği için muhtemelen kalıcı değildir. Dolayısıyla / users? Email = {email} bunun gerçekten bir sorgu olduğunu ve kalıcı tanımlayıcıya sahip bir kaynağa erişim olmadığını açıkça belirtir.
lex82

Bunun aslında daha doğru cevap olduğuna inanıyorum. Bir koleksiyonu e-posta adresine göre filtrelemek joker karakter tabanlı olabilir, bu nedenle her zaman yalnızca bir sonuç döndürmez.
Kevin M

@VinaySahni: /user?by=email&email="abc@pqr.com "/ user? By = id & id =" xashkhx "/ users? FilterA =" a "& filterB =" b "(çoğul birden çok kullanıcı için)
Shasak

2

Kullanıcı kaynakları hakkında

yolda /usersher zaman döndürülen kullanıcı kaynakları koleksiyonunu alırsınız.

yolda /users/[user_id]birkaç şeyin olmasını bekleyebilirsiniz:

  1. [user_id] tanımlayıcısıyla kullanıcı kaynağını temsil eden bir tekil kaynak almalısınız veya
  2. [user_id] kimliğine sahip bir kullanıcı yoksa 404 bulunamadı yanıtı veya
  3. istenen kullanıcı kaynağına erişim izniniz yoksa yasak bir 401 .

Her bir singleton yolu ve tanımlayıcısı ile benzersiz bir şekilde tanımlanır ve kaynağı bulmak için bunları kullanırsınız. Tekil için birden fazla yol kullanmak mümkün değildir.

Yolu /userssorgu parametreleri ( GETParametreler) ile sorgulayabilirsiniz . Bu, istenen kriterleri karşılayan kullanıcılarla bir koleksiyon döndürecektir. Döndürülen koleksiyon, yanıttaki tanımlayıcı kaynak yollarıyla birlikte kullanıcı kaynaklarını içermelidir.

Parametreler, koleksiyonun kaynaklarında bulunan herhangi bir alan olabilir; firstName, lastName,id

E-posta hakkında

E-posta, bir kaynak veya kullanıcı kaynağının bir özelliği / alanı olabilir.

- Kullanıcının özelliği olarak e-posta:

Alan, kullanıcının bir özelliğiyse, kullanıcı yanıtı şuna benzer:

{ 
  id: 1,
  firstName: 'John'
  lastName: 'Doe'
  email: 'john.doe@example.com'
  ...
}

Bu araçlar e-postalar için özel bir uç nokta yoktur, ama şimdi aşağıdaki isteği göndererek onun e-posta ile bir kullanıcı bulabilirsiniz: /users?email=john.doe@example.com. Hangi (e-postaların kullanıcılara özel olduğunu varsayarsak), e-postayla eşleşen bir kullanıcı öğesi içeren bir koleksiyon döndürür.

- Kaynak olarak e-posta:

Ancak kullanıcılardan gelen e-postalar da kaynaksa. Ardından /users/[user_id]/emails, kimliğine sahip kullanıcı için bir e-posta adresleri koleksiyonu döndüren bir API oluşturabilirsiniz user_id. /users/[user_id]/emails/[email_id]user_id ve ['email_id'] ile kullanıcının e-postasını döndürür. Tanımlayıcı olarak ne kullanacağın sana kalmış, ama ben bir tamsayıya bağlı kalırım. Silmek DELETEistediğiniz e-postayı tanımlayan yola bir istek göndererek kullanıcıdan bir e -postayı silebilirsiniz. Örneğin DELETE, tarihinde /users/[user_id]/emails/[email_id]user_id ile kullanıcıya ait olan email_id e-postasını silecektir. Büyük olasılıkla yalnızca bu kullanıcının bu silme işlemini gerçekleştirmesine izin verilir. Diğer kullanıcılar 401 yanıtı alacak.

Bir kullanıcının yalnızca bir e-posta adresi varsa, devam edebilirsiniz /users/[user_id]/email Bu, tek bir kaynak döndürür. Kullanıcı, e PUT-posta adresini bu url'deki e- posta adresini kullanarak güncelleyebilir .

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.