REST API istemcisi olarak bir Web uygulaması: kaynak tanımlayıcıları nasıl kullanılır


21

Uygulamayı denediğimde, REST ile ilgili birkaç kavram kafamda çatışıyor.

İş mantığını tutan bir REST ful ful API sistemine ve kullanıcı arayüzünü sağlayan bir web uygulamasına sahibim. REST ile ilgili çeşitli kaynaklardan (özellikle Uygulamadaki REST: Hypermedia ve Systems Architecture ) Varlıklarımın ham tanımlayıcılarını göstermemeliyim, köprüleri geri getirmem gerektiğini biliyorum rel="self".

Örnek düşünün. REST api bir kişiyi döndüren bir kaynağa sahiptir:

<Person>
  <Links>
    <Link rel="self" href="http://my.rest.api/api/person/1234"/>
  </Links>
  <Pets>
    <Link rel="pet" href="http://my.rest.api/api/pet/678"/>
  </Pets>
</Person>

Sorun web uygulaması ile ortaya çıkar. Tarayıcılara köprü içeren bir sayfa döndürdüğünü varsayalım:

<body class="person">
  <p>
    <a href="http://my.web.app/pet/???????" />
  </p>
</body>

Özelliğe ne koymalıyım href? Bir kullanıcı hedef sayfayı açtığında varlık varlık URL'sini web uygulamasında nasıl tutabilirim?

Gereksinimler çelişkili görünüyor:

  1. Köprü hrefweb uygulamasına yönlendirmelidir, çünkü bu UI'yi barındıran sistemdir
  2. hrefWeb uygulaması hedef sayfası açıldığında varlık ele almak gerekir, çünkü varlığın bazı kimliğine sahip olmalıdır
  3. Web uygulaması REST URL'lerini ayrıştırmamalı / inşa etmemelidir, çünkü bu REST-ful değildir.

URI'ler tüketicilere şeffaf olmamalıdır. Sadece URI'yi veren kişi, nasıl yorumlanacağını ve bir kaynağa eşleneceğini bilir.

Bu nedenle, yalnızca 1234API yanıt URL’sini alamıyorum , çünkü RESTful bir müşteri olarak ona sanki bir şeymiş gibi davranmalıyım http://my.rest.api/api/AGRIDd~ryPQZ^$RjEL0j. Diğer taraftan, web uygulamamı yönlendiren bir URL vermeliyim ve uygulamanın bir şekilde API'nin orijinal URL'sini geri yüklemesi ve API kaynaklarına erişmek için bu URL'yi kullanması için yeterli.

En basit yöntem muhtemelen kaynakların API URL'lerini dize tanımlayıcıları olarak kullanmaktır. Ancak web sayfası URL'leri gibi http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234çirkin.

Her şey bir masaüstü uygulaması veya tek sayfalık bir javascript uygulaması için oldukça kolay görünüyor. Sürekli yaşadıkları için, URL'leri uygulama ömrü boyunca hizmet nesneleriyle birlikte bellekte tutabilir ve gerektiğinde kullanabilirler.

Bir web uygulamasıyla birkaç yaklaşım hayal edebiliyorum, ancak hepsi garip görünüyor:

  1. Ana makineyi API URL'lerinde değiştirin ve yalnızca sonucu saklayın. Büyük dezavantajı, web uygulamasının, API'nin oluşturduğu URL'yi ele almasını gerektirmesidir, yani canavarca kuplaj anlamına gelir. Ayrıca, bir daha RESTful değil, çünkü web uygulamam URL’leri yorumlamaya başladı.
  2. REST API'sindeki ham kimlikleri bağlantılarla birlikte gösterin, Web Uygulaması URL'lerini oluşturmak için bunları kullanın ve ardından API'deki gerekli kaynakları bulmak için web uygulaması sunucusundaki kimlikleri kullanın. Bu daha iyidir, ancak web uygulaması sunucu performansını etkileyecektir, çünkü web uygulamasının bir tarayıcıdan gelen herhangi bir isteği yerine getirmek için bir formun kimlik doğrulama istekleri zincirini yayınlayan REST servis navigasyonundan geçmesi gerekecektir. Biraz iç içe geçmiş bir kaynak için bu pahalı olabilir.
  3. selfApi tarafından döndürülen tüm URL'leri web uygulaması sunucusunda kalıcı (DB?) Eşlemede saklayın. Onlar için bazı kimlikler oluşturun, web uygulaması sayfa URL'lerini oluşturmak ve REST hizmeti kaynaklarının URL'lerini almak için kimlikleri kullanın. Yani http://my.rest.api/pet/678URL'yi yeni bir anahtarla bir yerde tutuyorum, diyorum 3ve web sayfası URL'sini olarak oluşturuyorum http://my.web.app/pet/3. Bu, bir tür HTTP Önbelleği uygulaması gibi görünüyor. Nedenini bilmiyorum ama bana çok garip geliyor.

Yoksa hepsi RESTful API'lerin web uygulamaları için arka uç olarak kullanamayacağı anlamına mı geliyor?


1
Neyi başarmaya çalıştığınızın net olmadığı, muhtemelen basit niyetiniz birbirinin üzerine koyduğunuz mimari katmanların altında olduğu için, “RESTful API'lerin” size gerçekten yardım edip etmeyeceğini söylemek zordur. Sorununuzu anladığım kadarıyla, seçenek 2 basit ve uygulanabilir bir çözümdür. Buradaki "sorun", "RESTful API'lere" özgüdür. RestIsJustSqlReinvented ve gerçekten herhangi bir RDBMS'den yeterince karmaşık bir alt yazı almaya çalıştığınızda aynı sorunu yaşarsınız . Sorgularınız için optimize edilmiş bir önbellek veya sunum kullanın.
back2dos

Yanıtlar:


5

Soru güncellemelerini ele almak üzere düzenlendi, önceki yanıt kaldırıldı

Sorunuzdaki değişikliklerinizi inceleyince, karşılaştığınız sorunu biraz daha fazla anlıyorum. Kaynaklarınızda tanımlayıcı olan bir alan olmadığı için (yalnızca bir bağlantı) GUI'nizdeki o belirli kaynağa (yani belirli bir evcil hayvanı tanımlayan bir sayfaya bağlantı) gönderme imkânınız yoktur.

Belirlenecek ilk şey, bir evcil hayvan sahibi olmadan bir anlam ifade edip etmediğidir. Eğer sahibi olmayan bir evcil hayvanımız olabilirse, o zaman evcil hayvan üzerinde atıfta bulunmak için kullanabileceğimiz bir tür benzersiz mülke ihtiyacımız olduğunu söyleyebilirim. Asıl kaynak kimliği hala REST istemcisinin ayrıştırmayacağı bir bağlantıda gizlenebileceğinden, kimliği doğrudan göstermemeyi ihlal edeceğini sanmıyorum. Bunu göz önüne alarak evcil hayvan kaynağımız şöyle görünebilir:

<Entity type="Pet">
    <Link rel="self" href="http://example.com/pets/1" />
    <Link rel="owner" href="http://example.com/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

Artık uygulamadaki herhangi bir kaynak kimliğini karıştırmak zorunda kalmadan o evcil hayvanın adını Spot'tan Fido'ya güncelleyebiliriz. Aynı şekilde GUI'mizdeki o hayvana şöyle bir şey söyleyebiliriz:

http://example.com/GUI/pets/Spot

Evcil hayvan sahibi olmadan herhangi bir anlam ifade etmiyorsa (veya sistemde sahibi olmayan evcil hayvanlara izin verilmiyorsa) sahibi, sistemdeki evcil hayvanın "kimliğinin" bir parçası olarak kullanabiliriz:

http://example.com/GUI/owners/John/pets/1 (John için listedeki ilk evcil hayvan)

Küçük bir not, hem Hayvanlar hem de İnsanlar birbirinden ayrı olarak bulunabilirse, API için giriş noktasını "Kişiler" kaynağı yapmazdım. Bunun yerine, İnsan ve Evcil Hayvanlara bağlantı içeren daha genel bir kaynak oluşturacağım. Şuna benzeyen bir kaynak döndürebilir:

<Entity type="ResourceList">
    <Link rel="people" href="http://example.com/api/people" />
    <Link rel="pets" href="http://example.com/api/pets" />
</Entity>

Bu nedenle, yalnızca API'ye ilk giriş noktasını bilmek ve sistem tanımlayıcılarını bulmak için herhangi bir URL'yi işlememekle şöyle bir şey yapabiliriz:

Kullanıcı uygulamaya giriş yapar. REST istemcisi, aşağıdaki gibi görünen mevcut tüm insan kaynakları listesine erişir:

<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/1" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/1" />
        <Link rel="pet" href="http://example.com/api/pets/2" />
    </Pets>
    <UniqueName>John</UniqueName>
</Entity>
<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/2" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/3" />
    </Pets>
    <UniqueName>Jane</UniqueName>
</Entity>

GUI, her bir kaynak arasında döngü kurar ve "ID" olarak UniqueName kullanan her kişi için bir liste öğesi yazdırır:

<a href="http://example.com/gui/people/1">John</a>
<a href="http://example.com/gui/people/2">Jane</a>

Bunu yaparken bir "evcil hayvan" rel ile bulduğu her bir bağlantıyı da işleyebilir ve aşağıdaki gibi evcil hayvan kaynağını alabilir:

<Entity type="Pet">
    <Link rel="self" href="http://example.com/api/pets/1" />
    <Link rel="owner" href="http://example.com/api/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

Bunu kullanarak aşağıdaki gibi bir link yazdırabilir:

<!-- Assumes that a pet can exist without an owner -->
<a href="http://example.com/gui/pets/Spot">Spot</a>

veya

<!-- Assumes that a pet MUST have an owner -->
<a href="http://example.com/gui/people/John/pets/Spot">Spot</a>

Eğer ilk linke gidersek ve giriş kaynağımızın "evcil hayvanlar" ile olan bir bağı olduğunu varsayarsak, kontrol akışı GUI'de şöyle bir şey olur:

  1. Sayfa açılır ve evcil hayvan Noktası talep edilir.
  2. Kaynak listesini API giriş noktasından yükleyin.
  3. "Evcil" terimiyle ilgili olan kaynağı yükleyin.
  4. Her bir kaynağa "evcil hayvan" yanıtından bakın ve Spot ile eşleşen bir kaynak bulun.
  5. Spot için bilgileri görüntüleyin.

İkinci bağlantının kullanılması, Kişilerin API'ye giriş noktası olması ve ilk önce sistemdeki tüm insanların bir listesini alacağımız, eşleşen olanı bulacağımız, sonra ait olan tüm evcil hayvanların bulunduğu bir istisna zinciriyle benzer bir olaylar zinciri olacaktır. o kişiye (rel etiketini tekrar kullanarak) ve Spot adında birini bulun, böylece onunla ilgili belirli bilgileri görüntüleyebiliriz.


Sağol Mike. Sorunu biraz daha net hale getirmek için güncellendi. Cevabınızdaki sorun, bir REST istemcisinin URL’leri ayrıştırabileceğini kabul edemem. Olursa, URL'lerle birleştirilir. Bu da REST'in temel fikirlerinden birini ihlal ediyor: müşteriler relbağlantıları seçmek için s kullanmalı , ancak URL'lerin yapısı hakkında herhangi bir bilgi edinmemelidir. REST, bir API’nin, relaynı kalması şartıyla URL’leri değiştirmekte serbest olduğunu iddia eder . URL’leri ayrıştırmak bizi SOAP’a REST’ten daha yaklaştırır.
Pavel Gatilov

Tekrar teşekkürler. Şimdiye kadar uyguladığımız yaklaşımı tanımladınız. Bir şekilde, tanımlayıcıları açığa çıkarırız. Tek şey, mümkün olduğunca doğal tanımlayıcıları ortaya çıkarmaya çalışmamızdır.
Pavel Gatilov

6

Tüm bunlar RESTful API'lerin web uygulamaları için arka uç olarak kullanamayacağı anlamına mı geliyor?

Bir REST API'si ile bir web uygulaması arasında ayrım yapmanın faydalı olup olmadığını düşünüyorum. "Web uygulamanız" yalnızca aynı kaynakların alternatif (HTML) temsilleri olmalıdır - yani, nasıl ve neden erişmeyi umduğunuzu http://my.rest.api/...ve http://my.web.app/...aynı anda aynı ve farklı olduklarını anlamıyorum .

"İstemciniz" bu durumda tarayıcıdır ve HTML ve JavaScript'i anlar. Yani olan Bence web uygulaması. Artık foo.com'u kullanarak bahsi geçen web uygulamasına eriştiğini ve api.foo.com aracılığıyla her şeyi açığa çıkardığınızı düşünebilirsiniz - ama sonra sormak zorundasınız, foo.com bana kaynağın sunumunu nasıl sağladı? Foo.com'un "arka ucu" api.foo.com adresinden kaynakları nasıl keşfedeceğinizi mükemmel bir şekilde bilir. Web uygulamanız yalnızca bir proxy haline geldi - başka bir API ile (başka birinden) birlikte konuşmanızdan farklı değil.

Bu nedenle sorunuz, "Diğer sistemlerde bulunan kendi URI'larımı kullanarak kaynakları nasıl tanımlayabilirim?" Şeklinde genelleştirilebilir. bunun nasıl yapıldığını anlaması gereken müşteri (HTML / JavaScript) olmadığını düşündüğünüzde önemsizdir. İlk meydan okumamı kabul ediyorsanız, web uygulamanızı yalnızca başka bir REST API'sine vekalet eden veya temsil eden ayrı bir REST API'si olarak düşünebilirsiniz.

Böylece, müşteriniz eriştiğinde my.web.app/pets/1evcil hayvan arayüzünü sunmayı bilir, çünkü sunucu tarafı şablonunun döndürdüğü şey budur ya da başka bir gösterim için eşzamansız bir istekse (örn. JSON veya XML), içerik tipi başlığı bunu söyler. .

Bunu sağlayan sunucu, bir evcil hayvanın ne olduğunu ve uzak sistemdeki bir evcil hayvanı nasıl keşfettiğini anlamaktan sorumludur. Bunu nasıl yapacağınız size kalmış - kimliğinizi alabilir ve uygunsuz olduğunu düşündüğünüz başka bir URI oluşturabilir veya uzak URI'yi depolayan ve isteği proxy'leyen kendi veritabanınıza sahip olabilirsiniz. Bu URI’yi saklamak gayet iyi - yer imi ile eşdeğer. Bunları sadece ayrı bir alan adına sahip olmak için yapıyor olmalısınız. Bunu neden istediğinizi dürüstçe bilmiyorum - REST API URI'leriniz de yer imine uygun olmalıdır.

Sorunuzun çoğunda bu konuyu zaten gündeme getirdiniz, ancak bunu yapmak istediğinizi yapmanın pratik bir yol olduğunu gerçekten kabul etmeyecek şekilde çerçevelemiş olduğunuzu hissediyorum ( isteğe bağlı kısıtlama - API ile uygulamanın ayrı olması). REST API'lerinin web uygulamaları için arka uç olup olmayacağını sorarak ve performansın bir sorun olacağını öne sürerek, her şeyi yanlış şeylere odakladığınızı düşünüyorum. Mashup oluşturamayacağınızı söylemek gibi. Webin işe yaramadığını söylemek gibi.


Web uygulamasının sadece api'nin temsili olmasını beklemiyorum. Pek çok farklılığı olabilir, örneğin, birkaç sayfa kaynağını tek bir sayfada bir tane kök ile birlikte gösterir. 2 uygulamanın aynı olmasını beklediğimi söyleyerek, web uygulaması url'lerinin api veri deposunun iç kimliklerini içermesini istemiyorum. Buradaki performansla ilgilenmiyorum, sorun değil. Asıl soru, ' my.web.app/pets/3REST API URL'lerini ayrıştırmadan 3'ü nasıl girebilirim ?
Pavel Gatilov

Kendi ifadelerimi düzeltme: 'İlgili my.web.app/pets/3REST API kaynağının URL’sini ayrıştırmadan 3’ü nasıl girerim my.rest.api/v0/persons/2/pets/3? Veya oraya ne koyacağım?
Pavel Gatilov

Sanırım müşterinin durumunu, bu durumu belirleyen temsillerle karıştırıyorsunuz. Sen koymayın 3içinde app/pets/3çünkü app/pets/3opak, bu web uygulaması ne isterse kaynak işaret ediyor. Bu, diğer bazı kaynaklardan oluşan bir görünümse (diğer sistemlerde - API'niz bunlardan biri), o zaman köprülerinizi web uygulaması sunucusundaki sistemlere depolamak ve sonra bunları almak, bunların temsillerini çözmek için size bağlıdır ( örneğin, JSON veya XML) ve ardından yanıtınızın bir parçası olarak onlara hizmet edin.
Doug

Bunu bu şekilde düşünün - API'nızı ve Uygulamanızı unutun. İnsanların en sevdikleri Facebook ve Twitter yayınlarını toplayabilmelerini sağlayan bir site oluşturmak istediğinizi varsayalım. Bunlar uzak sistemlerdir. URI'leri bu sistemler için kendi tünelinizden tünellemeye veya şablonlamaya çalışmayacaksınız. Bir 'board' kaynağı yaratırsınız ve bu bunu işaret eden sunucunuz board/1olur facebook.com/post/123ve twitter.com/status/789- panonuzun bir gösterimini sağladığınızda, bu URI'ları üzerinde çalışabileceğiniz bir temsilci ile çözmek zorunda kalırsınız. Gerektiğinde önbellek.
Doug

Ve böylece, API'nizin uygulamanızdan önemli ölçüde farklı olmasını istediğinizden (bunun hala sorgulanabilir olduğunu düşünüyorum) - uzak bir sistem gibi davranmak bundan farklı olmaz. Performansın sorun olmadığını söylemiştiniz, ancak sorunuzda böyle bir şeyin 'performansı etkileyeceğini' söylediniz.
Doug

5

önsöz

Bu cevap özellikle, arka uç REST API'sinin açıkça bir tanımlayıcıyı ortaya koymadığı ve API tarafından sağlanan URL'leri yorumlamayan kaynaklar için benzersiz yer imlerine eklenebilir URL'ler de dahil olmak üzere kendi URL şemanızı nasıl yöneteceğiniz sorusunu ele almaktadır.


Keşfedilebilirlik belirli miktarda bilgi gerektirir.

Diyelim ki http://my.web.app/person, sonuçların her biri için ayrıntılar sayfasına bir bağlantı içerdiği bir arama sayfası istiyoruz . Bizim ön uç kodu bir şey olmalı hiç bir şey yapmak için biliyorum onun DİNLENME veri kaynağı için baz URL: http://my.rest.api/api. Bu URL’ye bir GET isteğinin cevabı şöyle olabilir:

<Links>
    <Link ref="self" href="http://my.rest.api/api" />
    <Link rel="person" href="http://my.rest.api/api/person" />
    <Link rel="pet" href="http://my.rest.api/api/pet" />
</Links>

Niyetimiz bir kişi listesi göstermek olduğundan, daha sonra geri dönebilecek olan bağlantı hrefinden GEThref'e bir istek göndeririz person:

<Links>
    <Link ref="self" href="http://my.rest.api/api/person" />
    <Link rel="search" href="http://my.rest.api/api/person/search" />
</Links>

Arama sonuçlarını görüntülemek istiyoruz, bu nedenle geri dönebilecek olan bağlantı hrefine bir GETistek göndererek arama hizmetini kullanacağız search:

<Persons>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/1"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/10"/>
        </Pets>
    </Person>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/2"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/20"/>
        </Pets>
    </Person>
</Persons>

Sonunda sonuçlarımız var, ancak ön uç URL'lerimizi nasıl oluştururuz?

Kesin olarak bildiğimiz kısmı çıkartalım: API temel URL'si ve gerisini ön uç tanımlayıcımız olarak kullanın:

  • bilinen API tabanı: http://my.rest.api/api
  • Bireysel varlık için verilen URL: http://my.rest.api/api/person/1
  • benzersiz kimlik: /person/1
  • temel URL’miz: http://my.web.app
  • oluşturulan ön uç URL’miz: http://my.web.app/person/1

Sonuçlarımız şöyle görünebilir:

<ul>
    <li><a href="http://my.web.app/person/1">A person</a></li>
    <li><a href="http://my.web.app/person/2">A person</a></li>
</ul>

Bir kullanıcı bir kez URL biz göndermek ne kadar ayrıntılar sayfasına o ön uç bağlantıyı izlediğinde GETo spesifik detaylar için istek person? Arka uç URL'leri ön uç URL'lerle eşleştirme yöntemimizi biliyoruz, bu nedenle tam tersi:

  • ön uç URL: http://my.web.app/person/1
  • temel URL’miz: http://my.web.app
  • benzersiz kimlik: /person/1
  • bilinen API tabanı: http://my.rest.api/api
  • oluşturulan API URL'si: http://my.rest.api/api/person/1

REST API, bir personURL'nin şimdi olduğu http://my.rest.api/api/different-person-base/person/1ve birisinin daha önce yer işareti koymuş http://my.web.app/person/1olduğu şekilde değiştiyse, REST API'sinin (en azından bir süre) eski URL'ye yenisini yönlendirerek yanıt vererek geriye dönük uyumluluk sağlaması gerekir. Üretilen tüm ön uç bağlantıları yeni yapıyı otomatik olarak içerecektir.

Muhtemelen fark ettiğiniz gibi, API'de gezinmek için bilmemiz gereken birkaç şey var:

  • API temel URL'si
  • personilişki
  • searchilişki

Bunda yanlış bir şey olduğunu sanmıyorum; Herhangi bir noktada belirli bir URL yapısını varsaymıyoruz, bu nedenle varlık URL’inin yapısı http://my.rest.api/api/person/1değişebilir ve API geriye dönük uyumluluk sağladığı sürece kodumuz çalışmaya devam eder.


Yönlendirme mantığımızın iki ön uç URL arasındaki farkı nasıl söyleyebileceğini sordunuz:

  • http://my.rest.api/api/person/1
  • http://my.rest.api/api/pet/3.

Öncelikle, örneğimizde UI ve REST API'si için ayrı taban URL'ler kullanırken, yorumunuzda API tabanını kullandığınızı belirteceğim. Ayrı üsler kullanarak örneğe devam edeceğim, ancak bir tabanı paylaşmak sorun değil. İsteğin Kabul başlığındaki ortam türünü kullanarak UI yönlendirme yöntemlerini eşleyebilir (veya yapabilmeliyiz).

Belirli bir ayrıntı sayfasına yönlendirmeye gelince self, API tarafından sağlanan URL'nin yapısı hakkında herhangi bir bilgiden kaçınmak konusunda katıysak bu iki URL'yi ayırt edemeyiz (örn. Opak dize kimliği). Bu işi yapmak için, ön uç URL'lerimizde bilinen bir bilgi parçasını - birlikte çalıştığımız varlık türünü - ekleyelim.

Önceden, ön uç URL'lerimiz aşağıdaki biçimdeydi: ${UI base}/${opaque string id}

Yeni format olabilir: ${UI base}/${entity type}/${opaque string id}

Yani /person/1örneği kullanarak, sonunda oluruz http://my.web.app/person/person/1.

Bu formatla, UI yönlendirme mantığımız çalışacak /person/person/1ve dizedeki ilk belirtecin kendimiz tarafından eklendiğini bilerek, onu çıkarabilir ve buna göre uygun (bu örnekte, kişi) detay sayfasına yönlendirebiliriz. Eğer bu URL’yi çok garip hissediyorsanız, oraya biraz daha ekleyebiliriz; olabilir: http://my.web.app/person/detail/person/1

Bu durumda /person/detail, yönlendirme için ayrıştırırız ve gerisini opak dize kimliği olarak kullanırız.


Bunun web uygulamasının api'ye son derece sıkı bir şekilde bağlandığını düşünüyorum.

Sanırım, oluşturulan ön uç URL’miz API URL’sinin bir bölümünü içerdiğinden, API URL yapısı eski yapıyı desteklemeden değişirse, yer imi verilen URL’yi URL’ye çevirmek için bir kod değişikliğine ihtiyacımız olacak. API URL’nin yeni sürümü. Başka bir deyişle, REST API bir kaynağın kimliğini (opak dizgi) değiştirirse, o zaman eski kimliği kullanarak kaynakla sunucudan konuşamayız. Bu durumda bir kod değişikliğinden kaçınabileceğimizi sanmıyorum.

Web uygulamasının URL yapısının API'nin yapısından farklı olmasını istersem ne olur?

İstediğiniz URL yapısını kullanabilirsiniz. Günün sonunda, belirli bir kaynak için yer imlerine eklenebilir bir URL, bu kaynağı benzersiz bir şekilde tanımlayan bir API URL’si almak için kullanabileceğiniz bir şey içermelidir. Kendi tanımlayıcınızı oluşturur ve onu # 3 yaklaşımınızdaki API URL'si ile önbelleğe alırsanız, bu giriş önbellekten temizlendikten sonra birileri bu yer imi verilen URL’yi kullanmaya çalışıncaya kadar çalışır.

Web uygulamamın varlıkları 1-1 api ile eşleşmediyse ne olur?

Cevap ilişkiye bağlı. Her iki durumda da, ön ucu API URL'leri ile eşleştirmek için bir yol gerekir.


Bu yaklaşımla ilgili bir sorunum var. Aslında çözüm listemdeki 1 numara. Anlamadığım şey şudur: web uygulaması URL'leri yorumlamaz ve benzersiz kimlikleri opak dizeler (sadece person/1, pet/3) olarak değerlendirirse, bir tarayıcı açarsa http://my.rest.api/api/person/1kullanıcı UI'sını göstermesi gerektiğini ve açılır http://my.rest.api/api/pet/3, sonra evcil hayvan Arabirimi?
Pavel Gatilov

İyi soru! Cevabımla cevabı güncelledim.
Mike Partridge

Sağol Mike. Bunun web uygulamasının api'ye son derece sıkı bir şekilde bağlandığını düşünüyorum. Web uygulamasının URL yapısının API'nin yapısından farklı olmasını istersem ne olur? Web uygulamamın varlıkları 1-1 api ile eşleşmediyse ne olur? Hala bazı tanımlayıcıları açığa vurma yaklaşımını benimsemeyi düşünüyorum, ancak müşterileri navigasyon için bağlantılar kullanmaya çağırıyor.
Pavel Gatilov

Bu ilginç bir konudur, umarım hiçbir şey kaçırmıyorum. Cevabımı yorumunuzu yanıtlayarak güncelleştirdim. Bazı tanımlayıcıları açığa vurmak, tam RESTfullık ile kullanılabilirlik arasında iyi bir uzlaşma olduğunu düşünüyorum.
Mike Partridge,

Buradaki birincil endişem biraz daha pratik. Web uygulamasını uygulamak için ASP.NET MVC kullanıyorum ve bazı iç kurallar nedeniyle uygulamanın desteklediği url kalıplarını tanımlamalıyım. Yani, eğer / a / {id} tanımlanmışsa, uygulama / a / 1 'i idare edecektir, fakat / a / 1 / b / 2' yi kullanmayacaktır. Bu, REST API'si yalnızca yer imlerine eklenmiş URL'leri korumak için değil, aynı zamanda sadece web uygulamasından kökünden giderken çalışmasını sağlamak için yapılan URL’leri değiştirirse, web uygulamasını yeniden derleme gereksinimine yol açar. Bunun nedeni, html sayfalarına gömülü köprüler, onsuz çalışmaz.
Pavel Gatilov

2

Kabul edelim, sihirli bir çözüm yok. Richardson Olgunluk Modelini okudunuz mu? REST mimarisi olgunluğunu 3 seviyeye ayırır: Kaynaklar, HTTP fiilleri ve hypermedia kontrolleri.

Varlıklarımın ham tanımlayıcılarını göstermemeliyim, ancak rel = "self" ile köprüleri döndürmeliyim

Bu hypermedia kontrolleri. Buna gerçekten ihtiyacın var mı? Bu yaklaşımın bazı çok iyi faydaları vardır ( burada onlar hakkında okuyabilirsiniz ). Ancak ücretsiz yemek diye bir şey yoktur ve onları almak istiyorsanız çok çalışmak zorunda kalacaksınız (örneğin ikinci çözümünüz).

Bu bir denge sorunudur - performanstan ödün vermek (ve kodunuzu daha karmaşık hale getirmek) ancak daha esnek bir sistem mi elde etmek istiyorsunuz? Yoksa işleri daha hızlı ve basit tutmayı mı tercih edersiniz, ancak daha sonra api / modelinizde değişiklikler yaptığınızda ödeme yapar mısınız?

Benzer bir sistem geliştiren biri olarak (iş mantığı katmanı, web katmanı ve web müşterileri) ikinci seçeneği seçtim. Grubum tüm katmanları geliştirdiğinden, biraz eşleşmenin daha iyi olacağına karar verdik (web katmanının varlık kimlikleri ve api URL'leri hakkında bilgi vererek) ve bunun karşılığında daha basit olan kodları aldık. Bizim durumumuzda geriye dönük uyumluluk da önemli değildi.

Eğer web uygulaması bir 3. şahıs tarafından geliştirildiyse veya geriye dönük uyumluluk bir sorunsa, web uygulamasını değiştirmeden URL yapısını değiştirmede büyük bir değer olduğu için farklı seçmiş olabiliriz. Kodu zorlaştırmak için yeterli.

Tüm bunlar RESTful API'lerin web uygulamaları için arka uç olarak kullanamayacağı anlamına mı geliyor?

Bence mükemmel bir REST uygulaması oluşturmak zorunda değilsiniz. İkinci çözümünüzü kullanabilir veya varlık kimliğini gösterebilir veya belki api URL'lerini geçebilirsiniz . Etkilerini ve takaslarını anladığınız sürece sorun değil.


0

Sana benzer bir şeye sadık Atom Syndication Formatkalırsan iyi olur.

Burada, temsil edilmekte olan Girişi tanımlayan meta veriler, ek elemanlar / nitelikler kullanılarak belirtilebilir:

  • [RFC4287] uyarınca , Girişi benzersiz bir şekilde tanımlayan bir URI içeriyor

  • [RFC4287] uyarınca , bu eleman isteğe bağlıdır. İçerirse, URI içeriyorsa, bir müşteri Girişi almak için kullanmalıdır.

Bu sadece iki sentim.


Belki bir şey anlamadım, ama cevabınız bana bir REST API'sine istemci olan bir web uygulamasının URL'lerinin nasıl oluşturulacağını açıklamıyor, değil mi?
Pavel Gatilov

0

URL'ler için endişelenmeyin, medya türleri için endişelenmeyin.

Buraya bakın (özellikle üçüncü madde işareti noktası).

Bir REST API, kaynak göstermek ve uygulama durumunu desteklemek için kullanılan ortam türlerini tanımlamak veya mevcut standart ortam türleri için genişletilmiş ilişki adları ve / veya köprü metni etkin işaretlemeyi tanımlamak için tanımlayıcı çabasının neredeyse tamamını harcamalıdır. .


Tipik bir web uygulaması durumunda, müşteri bir insandır ; tarayıcı sadece bir ajandır .

Yani bir çapa etiketi gibi

          <a href="example.com/foo/123">click here</a>

gibi bir şeye karşılık gelir

          <link type="text/html" rel="self" href="example.com/foo/123">

URL, kullanıcı için hala opaktır, tek umursadığı medya türleridir (örn. text/html, application/pdf, application/flv, video/x-flv, image/jpeg, image/funny-cat-picture etc). Bağlantıda (ve başlık niteliğinde) bulunan açıklayıcı metin, ilişki türünü insanlar için anlaşılır bir şekilde genişletmenin bir yoludur.

URI'nın müşterilere opak olmasını istemenin nedeni, eşleşmeyi azaltmanızdır (REST'in temel amaçlarından biri). Sunucu, istemciyi etkilemeden URI'leri değiştirebilir / yeniden düzenleyebilir (iyi bir önbelleğe alma politikanız olduğu sürece - ki bu hiçbir önbelleğe alma anlamına gelmeyebilir).

Özetle

Sadece müşterinin (insan veya makine) URL'lerden ziyade medya türlerine ve ilişkilere önem verdiğinden emin olun.


Rodrick, sorum API'yı oluşturmakla ilgili değil, RESTful API'nin üzerine oturan bir web uygulaması oluşturmakla ilgili. Medya türlerinin web uygulaması için URL'ler oluşturmama nasıl yardım edebileceğini anlayamıyorum. Her ne kadar medya türleri servis sözleşmesi ve keşfedilebilirlik için çok önemlidir.
Pavel Gatilov

@PavelGatilov - Web uygulamanızın müşterisi bir insan mıdır?
Rodrick Chapman,

Evet öyle. Ve çok anlayışlı biri.
Pavel Gatilov

0

En basit yöntem muhtemelen kaynakların API URL'lerini dize tanımlayıcıları olarak kullanmaktır. Ancak, web sitesi http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234 gibi URL'leri çirkindir.

Bence haklısın, bu en basit yol. URL'leri http://my.rest.api/apidaha az çirkin yapmak için göreceli olarak aktarabilirsiniz :

http://my.web.app/person/person%2F1234

API tarafından sağlanan URL bu tabanla ilgili görünmüyorsa, çirkin forma indirgenir:

http://my.web.app/person/http%3A%2F%2Fother.api.host%2Fapi%2Fperson%2F1234

Bir adım daha ileri gitmek için, ne tür bir görünüm sunmak istediğinizi belirlemek için yol sunucusundaki yanıtı inceleyin ve yol segmenti sınırlayıcıyı ve virgülleri kodlamayı durdurmak için:

http://my.web.app/person/1234 (best case)
http://my.web.app/http://other.api.host/api/person/1234 (ugly case)
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.