API sürümleri için en iyi uygulamalar? [kapalı]


877

Web hizmeti REST API sürümlemesi için bilinen nasıl yapılır veya en iyi uygulamalar var mı?

AWS'nin uç noktanın URL'sine göre versiyonlama yaptığını fark ettim . Bu tek yol mu yoksa aynı hedefe ulaşmak için başka yollar var mı? Birden fazla yol varsa, her yolun değeri nedir?

Yanıtlar:


682

Bu iyi ve zor bir soru. Konu URI tasarımı olan aynı zamanda bir REST API en önemli parçası ve bu nedenle potansiyel olarak o API kullanıcılara karşı uzun vadeli taahhüt .

Daha az ölçüde bir uygulama ve, evrimi beri onun API hayatın bir gerçeği olduğunu ve bir programlama dili gibi görünüşte karmaşık ürünün evrimi bile benzer olduğunu, URI tasarım daha az olmalıdır doğal kısıtlamaları ve korunması gerektiğini zaman içinde . Uygulama ve API'nın ömrü ne kadar uzun olursa, uygulama ve API kullanıcılarına olan bağlılık da o kadar büyük olur.

Öte yandan, yaşamın başka bir gerçeği, API aracılığıyla tüketilecek tüm kaynakları ve yönlerini öngörmenin zor olmasıdır. Neyse ki, Apocalypse'a kadar kullanılacak tüm API'yı tasarlamak gerekli değildir . Her kaynak ve kaynak örneğinin tüm kaynak uç noktalarını ve adresleme şemasını doğru bir şekilde tanımlamak yeterlidir.

Zaman içinde her bir kaynağa yeni kaynaklar ve yeni öznitelikler eklemeniz gerekebilir, ancak API kullanıcılarının belirli bir kaynaklara erişmek için izledikleri yöntem, bir kaynak adresleme şeması herkese açık hale geldikten sonra değişmemelidir.

Bu yöntem, HTTP fiil semantiği (örn. PUT her zaman güncellenmeli / değiştirilmelidir) ve önceki API sürümlerinde desteklenen HTTP durum kodları (insan müdahalesi olmadan çalışan API istemcilerinin çalışmaya devam edebilmesi için çalışmaya devam etmelidir) için geçerlidir. bunun gibi).

Ayrıca, API sürümünün URI'ye gömülmesi, zaman içinde değişecek bir kaynak adresine / URI'ye sahip olarak uygulama devletinin motoru (Roy T. Fieldings Doktora tezinde belirtilmiştir) olarak hiper medya kavramını bozacağından, API'nın sürümler kaynak URI'larda uzun süre saklanmamalıdır ; bu , API kullanıcılarının bağlı olabileceği kaynak URI'lerin kalıcı bağlantı olması gerektiği anlamına gelir .

Tabii ki, API sürümünü temel URI'ye gömmek mümkündür, ancak yalnızca yeni API sürümüyle çalışan bir API istemcisinde hata ayıklamak gibi makul ve kısıtlı kullanımlar için . Bu tür sürümlendirilmiş API'ler, zaman sınırlı olmalı ve yalnızca sınırlı beta kullanıcıları için (kapalı beta'lar sırasında olduğu gibi) kullanılabilir olmalıdır. Aksi takdirde, kendinizi yapmamanız gereken yere bağlıyorsunuz.

Son kullanma tarihi geçen API sürümlerinin bakımı ile ilgili birkaç düşünce. Web hizmetlerini (Java, .NET, PHP, Perl, Rails, vb.) Uygulamak için yaygın olarak kullanılan tüm programlama platformları / dilleri, web hizmeti uç noktalarının temel URI'ye kolayca bağlanmasını sağlar. Bu şekilde , farklı API sürümlerinde bir dosya / sınıf / yöntem koleksiyonu toplamak ve ayrı tutmak kolaydır .

API kullanıcılarının POV'sinden, bu açık olduğunda ancak yalnızca sınırlı bir süre için, yani geliştirme sırasında belirli bir API sürümüyle çalışmak ve bunlara bağlanmak daha kolaydır.

API koruyucusunun POV'sinden, ağırlıklı olarak (kaynak kodu) sürümlemenin en küçük birimi olarak dosyalar üzerinde çalışan kaynak kontrol sistemlerini kullanarak farklı API sürümlerini paralel olarak korumak daha kolaydır.

Bununla birlikte, URI'de açıkça görülebilen API sürümlerinde bir uyarı vardır: API geçmişi URI tasarımında görünür / görünür hale geldiğinden ve bu nedenle REST yönergelerine aykırı değişikliklere yatkın olduğundan, bu yaklaşım da itiraz edilebilir . Katılıyorum!

Bu makul itirazın üstesinden gelmenin yolu, en son API sürümünü versiyonsuz API tabanı URI'sına uygulamaktır. Bu durumda, API istemci geliştiricileri şunlardan birini seçebilir:

  • en sonuncusuna karşı geliştirin (uygulamayı kötü tasarlanmış API istemcilerini kırabilecek nihai API değişikliklerinden koruyan uygulamayı sürdürmek için kendilerini taahhüt ederler ).

  • API'nın belirli bir sürümüne bağlanma (görünür hale gelir) ancak yalnızca sınırlı bir süre için

Örneğin, API v3.0 en son API sürümü ise, aşağıdaki iki takma ad olmalıdır (yani, tüm API isteklerine aynı şekilde davranmalıdır):

http: // shonzilla / api / müşteriler / 1234 
http: // shonzilla / api /v3.0 / müşteriler / 1234
http: // shonzilla / api / v3 / müşteriler / 1234

Buna ek olarak, eski API'yı göstermeye çalışan API istemcileri, kullandıkları API sürümü eskiyse veya artık desteklenmiyorsa , en son önceki API sürümünü kullanmaları konusunda bilgilendirilmelidir . Dolayısıyla, şu eski modaya uygun URI'lerden herhangi birine erişmek:

http: // shonzilla / api /v2.2 / müşteriler / 1234
http: // shonzilla / api /v2.0 / müşteriler / 1234
http: // shonzilla / api / v2 / müşteriler / 1234
http: // shonzilla / api /v1.1 / müşteriler / 1234
http: // shonzilla / api / v1 / müşteriler / 1234

HTTP üstbilgisiyle birlikte kullanılan ve bu kaynak olarak kalan uygun kaynak URI sürümüne yönlendiren 30x HTTP durum kodlarından herhangi birini döndürmelidir Location:

http: // shonzilla / API / müşteri / 1234

API sürüm senaryoları için uygun en az iki yönlendirme HTTP durum kodu vardır:

  • 301 İstenen bir URI'ye sahip kaynağın kalıcı olarak başka bir URI'ya (API sürüm bilgisi içermeyen bir kaynak örneği kalıcı bağlantısı olması gerektiğini) belirten kalıcı olarak taşındı. Bu durum kodu, API istemcisine, sürümlendirilmiş bir kaynak URI'nın bir kaynak kalıcı bağlantısıyla değiştirildiğini bildiren eski / desteklenmeyen bir API sürümünü belirtmek için kullanılabilir .

  • 302 İstenen kaynağın geçici olarak başka bir konumda bulunduğunu belirten bulunurken, talep edilen URI hala desteklenebilir. Bu durum kodu, sürümsüz URI'ler geçici olarak kullanılamıyorsa ve yeniden yönlendirme adresi kullanılarak bir isteğin tekrarlanması gerektiğinde (ör. APi sürümü katıştırılmış URI'yi işaret ederek) ve istemcilere kullanmaya devam etmesini söylemek istediğimizde (ör. kalıcı bağlantılar).

  • diğer senaryolar HTTP 1.1 spesifikasyonunun Yeniden Yönlendirme 3xx bölümünde bulunabilir


142
Temel uygulama değiştiğinde URL'de sürüm numarası kullanmak kötü bir uygulama olarak değerlendirilmemelidir. "Bir hizmetin arabirimi geriye dönük uyumlu olmayan bir şekilde değiştiğinde, gerçekte tamamen yeni bir hizmet yaratıldı ... Müşterinin bakış açısından, bir hizmet bir arabirimden ve bazı işlevsel olmayan niteliklerden başka bir şey değildir .. .Bir servisin arayüzü geriye dönük uyumlu olmayan bir şekilde değişirse, artık orijinal hizmetin bir örneğini temsil etmez, aksine tamamen yeni bir hizmettir. " ibm.com/developerworks/webservices/library/ws-version
benvolioT

7
İstemci veya geliştiriciler tarafından kontrol edilebilmesi için sürüm numarasına sahip bir başlık eklemekle ilgili düşünceleriniz var mı?
webclimber

11
Ayrıca, istemcinin beklediği sürümü belirtmek için bir Accept üst bilgisinin kullanımına bakın: blog.steveklabnik.com/2011/07/03/…
Weston Ruter

52
Son bölüm için: Artık kullanılmayan ve artık desteklenmeyen bir API'nin geri dönmesi gerektiğini söyleyebilirim 410 Gone, çünkü yönlendirme yeni konumun uygun olmadığında uyumlu olduğunu gösterebilir. API yalnızca eski olsa da hala mevcutsa, WarningYanıttaki bir HTTP Üstbilgisi bir seçenek olabilir.
Michael Stum

22
Şimdiden shonzilla / api / clients / 1234 gibi sabit URL kullanan müşterilerle nasıl başa çıkıyorsunuz ve yeni bir sürüme geçmek mi istiyorsunuz? URL'ye V2'yi (eskisini) eklemelerini nasıl zorlayabilirsiniz?
Dejell

273

URL, sürümleri İÇERMEMELİDİR. Sürümün, istediğiniz kaynağın "fikri" ile ilgisi yoktur. URL'yi, öğenin nasıl döndürülmesini istediğinize değil, istediğiniz konsepte giden bir yol olarak düşünmeye çalışmalısınız. Sürüm, nesne kavramını değil, nesnenin temsilini belirler. Diğer posterlerin söylediği gibi, istek üstbilgisinde biçimi (sürüm dahil) belirtmelisiniz.

Sürümleri olan URL'ler için tam HTTP isteğine bakarsanız, şuna benzer:

(BAD WAY TO DO IT):

http://company.com/api/v3.0/customer/123
====>
GET v3.0/customer/123 HTTP/1.1
Accept: application/xml

<====
HTTP/1.1 200 OK
Content-Type: application/xml
<customer version="3.0">
  <name>Neil Armstrong</name>
</customer>

Başlık, istediğiniz temsili içeren satırı içerir ("Accept: application / xml"). Bu sürümün gitmesi gereken yer. Herkes aynı şeyi farklı formatlarda isteyebileceğiniz ve müşterinin istediği şeyi sorabilmesi gerektiği konusunda parlak görünüyor. Yukarıdaki örnekte, istemci kaynağın HERHANGİ bir XML temsilini istemektedir - istediği şeyin gerçek temsilini değil. Sunucu, teorik olarak, XML olduğu sürece ve isteğin yanlış olduğunu fark etmek için ayrıştırılması gereken isteğe tamamen alakasız bir şey döndürebilir.

Daha iyi bir yol:

(GOOD WAY TO DO IT)

http://company.com/api/customer/123
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+xml

<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+xml
<customer>
  <name>Neil Armstrong</name>
</customer>

Ayrıca, müşterilerin XML'in çok ayrıntılı olduğunu düşündüklerini ve şimdi bunun yerine JSON'u istediklerini söyleyelim. Diğer örneklerde aynı müşteri için yeni bir URL'ye sahip olmanız gerekir, böylece aşağıdakilerle sonuçlanırsınız:

(BAD)
http://company.com/api/JSONv3.0/customers/123
  or
http://company.com/api/v3.0/customers/123?format="JSON"

(Veya benzeri). Aslında, her HTTP isteği aradığınız biçimi içerir:

(GOOD WAY TO DO IT)
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+json

<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+json

{"customer":
  {"name":"Neil Armstrong"}
}

Bu yöntemi kullanarak, tasarımda çok daha fazla özgürlüğe sahipsiniz ve aslında REST'in orijinal fikrine bağlı kalıyorsunuz. İstemcileri bozmadan sürümleri değiştirebilir veya API'ler değiştikçe istemcileri kademeli olarak değiştirebilirsiniz. Bir temsili desteklemeyi durdurmayı seçerseniz, isteklere HTTP durum kodu veya özel kodlarla yanıt verebilirsiniz. İstemci ayrıca yanıtın doğru biçimde olduğunu doğrulayabilir ve XML'yi doğrulayabilir.

Başka birçok avantajı var ve bunlardan bazılarını blogumda tartışıyorum: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html

URL'ye sürüm eklemenin ne kadar kötü olduğunu gösteren son bir örnek. Diyelim ki nesnenin içinde bir parça bilgi istiyorsunuz ve çeşitli nesnelerinizi versiyonladınız (müşteriler v3.0, siparişler v2.0 ve shipto nesnesine v4.2). İşte istemcide sağlamanız gereken kötü URL:

(Another reason why version in the URL sucks)
http://company.com/api/v3.0/customer/123/v2.0/orders/4321/

10
Accept üstbilgisinde bağımsız veri sözleşmesi sürümünü ve hizmet sözleşmesi sürümlerini işlemek, URL'de dağınık olduğu kadar dağınık görünür. Başka seçenek var mı? Ayrıca birden fazla uç noktam (sabun, dinlenme) varsa, bu da Kabuller bölümünde belirtilmeli ve sunucu sonundaki yönlendirme hizmetinin doğru uç noktaya yön karar vermesine izin vermeli VEYA uç noktanın URL'de kodlanması kabul edilebilir mi?
ideafountain

117
Buna, en azından son nedeninizin noktasına değinemem. Bu, URI'nin farklı bölümlerinin farklı sürümleri olduğunu söylüyor gibi görünüyor. Ancak bu bir API sürümünün amacı değildir. Buradaki nokta ENTIRE kaynağı için ONE sürümüne sahip olmaktır. Sürümleri değiştirirseniz, bu farklı bir API kaynağıdır. Bu nedenle company.com/api/v3.0/customer/123/v2.0/orders/4321 yerine şirket.com/api/v3.0/customer/123/orders/4321 adresini görmek mantıklı değil Kaynağın belirli bir bölümünü sürümlendirmiyorsunuz, kaynağı bir bütün olarak sürümlendiriyorsunuz.
fool4jesus

90
Süreli olarak başlıkta sürüm numarası kullanmak daha iyi görünüyor. Ancak URL'yi kullanmak çok daha pratiktir: daha az hataya eğilimli, en iyi hata ayıklama, geliştiriciler tarafından kolayca görülebilir, dinlenme testi istemcilerinde kolayca değiştirilebilir.
Daniel Cerecedo

7
Bence KÖTÜ / İYİ soruyu basitleştirir. API "Uygulama programlama arayüzü" anlamına gelir ve sürüm arayüzleri çok iyi bir fikir gibi görünmektedir. API'lar aslında sadece kaynak sunmakla ilgili değildir. Ayrılması gereken, bazı insanların arayüzler hakkında, diğer insanların kaynaklar hakkında konuşmasıdır. Google sekmesine api'yi ağ sekmesinde yakından incelerseniz, URL'ye api sürüm numarasını eklediklerini göreceksiniz. Örneğin: kimlik doğrulama sırasında maps.google.com/maps/api/jsv2. Jsv2, api numarasıdır.
Tom Gruner

6
@Gili: Aslında, artık RFC6648-x tarafından kullanımdan kaldırıldığı için kullanmamalısınız .
Jonathan W

98

Sürümü URL'ye koymanın pratik ve kullanışlı olduğunu gördük. Bir bakışta ne kullandığınızı anlatmayı kolaylaştırır. Kabul edilen yanıtın önerdiği gibi, kullanım kolaylığı, daha kısa / temiz URL'ler vb. İçin takma ad / foo / / foo / (en son sürümler) yapıyoruz.

Geriye dönük uyumluluğu sonsuza dek korumak genellikle maliyet engelleyici ve / veya çok zordur. Kullanımdan kaldırılma, burada önerildiği gibi yönlendirmeler, dokümanlar ve diğer mekanizmalar hakkında önceden bildirimde bulunmayı tercih ediyoruz.


5
Kabul edilen cevap doğru ve en saf olabilir. Bununla birlikte, API'ların geliştiricisi ve günlük kullanıcıları için bu kesinlikle kullanımı ve kurulumu en kolay olanıdır. En pragmatik yaklaşım. Diğer Google ve Amazon tarafından belirtildiği gibi bu yaklaşımı da kullanır.
Muhammad Rehan Saeed

46

Kaynak temsilinin sürümünün REST yaklaşımını daha iyi izlediğini kabul ediyorum ... ancak, özel MIME türleri (veya bir sürüm parametresi ekleyen MIME türleri) ile ilgili büyük bir sorun, Kabul Et ve İçerik Türü başlıklarına HTML'de yazmak için zayıf destek ve JavaScript.

Örneğin, bir kaynak oluşturmak için IMO'nun HTML5 formlarında aşağıdaki başlıklarla POST yapması mümkün değildir:

Accept: application/vnd.company.myapp-v3+json
Content-Type: application/vnd.company.myapp-v3+json 

HTML5 Bunun nedeni enctypenitelik normalden daha başka bir şey, bu nedenle, bir numaralandırma olduğunu application/x-www-formurlencoded, multipart/form-datave text/plaingeçersizdir.

... ne de HTML4'teki tüm tarayıcılarda desteklendiğinden emin değilim (daha gevşek bir encytpe özniteliğine sahiptir, ancak MIME türünün iletilip iletilmeyeceği konusunda bir tarayıcı uygulama sorunu olacaktır)

Bu nedenle, şimdi sürüm için en uygun yolun URI yoluyla olduğunu hissediyorum, ancak 'doğru' yol olmadığını kabul ediyorum.


14
Sürümlerin başlıklarda tanımlandığı rotayı varsayarsak, yerel form gönderimi kullanan HTML formlarının, uymak istedikleri belirli sürümü geçmeyecekleri için her zaman API'nın en son sürümünü kullanacakları söylenebilir. Ancak, XHR istekleri gerçekten kabulleri değiştirmenize ve içerik türü başlıklarını okumanıza izin verir. Temel formlar gerçekten tek sorun.
Kyle Hayes

URI'nın en uygun olduğunu kabul ettiğimden emin değilim, ancak Content-Type'ın formlarla çalışmadığı gerçeği gerçekten çok önemlidir.
wprl

2
@Kyle, bir yerde bir blog gördüm, istek başlığında bir sürümü belirtmezseniz, en iyi compatiable için en son sürümü olmayan ilk api sürümü ile dönmek en iyisidir dedi.
andy

Aslında düşündüğüm için bu bana çok mantıklı geliyor.
Kyle Hayes

@KyleHayes iframe'leri, video / embed ve diğer "src / href" tipi etiketleri unutmaz.
15'te

21

Sürümünüzü URI'ye yerleştirin. Bir API'nin bir sürümü her zaman diğerinin türlerini desteklemeyeceğinden, kaynakların yalnızca bir sürümden diğerine geçtiği iddiası basit bir şekilde yanlıştır. Biçimi XML'den JSON'a değiştirmekle aynı şey değildir. Türler olmayabilir veya anlamsal olarak değişmiş olabilir.

Sürümler kaynak adresinin bir parçasıdır. Bir API'dan diğerine yönlendiriyorsunuz. Başlıktaki adresleri gizlemek RESTful değildir.


13

Bir REST API'sinde sürüm oluşturma yapabileceğiniz birkaç yer vardır:

  1. Belirtildiği gibi, URI'de. Yönlendirmeler ve benzerleri iyi kullanılırsa bu izlenebilir ve hatta estetik olarak hoş olabilir.

  2. Accepts: üstbilgisinde, sürüm dosya türünde olur. 'Mp3' vs 'mp4' gibi. Bu da işe yarayacak, ancak IMO biraz daha az çalışıyor ...

  3. Kaynağın kendisinde. Birçok dosya biçiminin sürüm numaraları, genellikle üstbilgi içine gömülüdür; bu, yeni yazılımın dosya türünün tüm mevcut sürümlerini anlayarak 'çalışmasına' izin verirken, daha eski bir yazılım desteklenmeyen (daha yeni) bir sürüm belirtilirse punt yapabilir. Bir REST API bağlamında, URI'lerinizin hiçbir zaman değişmesi gerekmediği anlamına gelir, sadece verdiğiniz belirli veri sürümüne verdiğiniz yanıt.

Üç yaklaşımı da kullanmanın nedenlerini görebiliyorum:

  1. 'temiz süpürme' yeni API'leri yapmak isterseniz veya böyle bir yaklaşımın bulunduğu büyük sürüm değişiklikleri için.
  2. istemcinin işe yarayıp yaramayacağını bir PUT / POST yapmadan önce bilmesini istiyorsanız.
  3. eğer müşteri işe yarayıp yaramayacağını öğrenmek için PUT / POST yapmak zorundaysa.

8

REST API'nizin sürümlendirilmesi, diğer API'lerin sürümlerine benzer. Küçük değişiklikler yerinde yapılabilir, büyük değişiklikler tamamen yeni bir API gerektirebilir. Sizin için en kolayı, her seferinde sıfırdan başlamaktır, bu da URL'ye sürüm koymak en mantıklıdır. İstemci için hayatı kolaylaştırmak istiyorsanız, kullanımdan kaldırma (kalıcı yönlendirme), çeşitli sürümlerdeki kaynaklar vb. İle yapabileceğiniz geriye dönük uyumluluğu sürdürmeye çalışırsınız. Ancak REST'in "Serin URI'ler değişmediği" konusunda teşvik ettiği de budur.

Sonunda diğer API tasarımları gibi. Müşteri rahatlığına karşı çaba sarf edin. API'nız için semantik sürüm oluşturmayı kabul edin, bu da müşterilerinize yeni sürümünüzün ne kadar geriye dönük olarak uyumlu olduğunu netleştirir.

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.