REST API'si tek bir bileşik kaynak olarak birden çok kaynak döndürebilir mi?


10

Bir REST API oluşturma aşamasındayım ve şu anda aşağıdaki sorunla karşılaşıyorum:

  • Fooilk kaynaktır. CRUD işlemleri /foo/URI aracılığıyla uygulanabilir .
  • Barikinci kaynaktır. CRUD işlemleri /bar/URI aracılığıyla uygulanabilir .
  • Her Foobiri sıfır veya bir ile ilişkilidir Bar. BarBir alt kaynak olarak davranmamamın Foonedeni, aynı Barörneğin mutiple Foos arasında paylaşılabilmesidir . Bu yüzden, bunun yerine bağımsız bir URI ile erişmenin daha iyi olduğunu düşündüm /foo/[id]/bar.

Benim sorunum önemli bir durumda, bir Fooörnek isteyen istemciler de ilişkili Barörnek ile ilgileniyor olmasıdır . Şu anda bu, bir yerine iki sorgu gerçekleştirmeleri gerektiği anlamına gelir. Her iki nesneyi tek bir sorgu ile almak için izin veren bir yol tanıtmak istiyorum, ama bunu yapmak için API modellemek için nasıl bilmiyorum. Şimdiye kadar ne buldum:

  • Ben buna benzer bir sorgu parametresi tanıtmak olabilir: /foo/[id]?include_bar=true. Bu yaklaşımla ilgili sorun, yanıtın kaynak gösteriminin (örn. JSON yapısı) farklı görünmesi gerektiğidir (örn { foo: ..., bar: ... }. Sadece serileştirilmiş yerine bir kap Foo), bu da Fookaynak uç noktasını "heterojen" kılar . Bunun iyi bir şey olduğunu düşünmüyorum. Sorgulama yapılırken /foo, sorgu parametrelerinden bağımsız olarak istemciler her zaman aynı kaynak gösterimini (yapısını) almalıdır.
  • Başka bir fikir, yeni bir salt okunur uç nokta eklemektir /fooandbar/[foo-id]. Bu durumda, böyle bir temsili iade etmek sorun değil { foo: ..., bar: ... }, çünkü o zaman fooandbarkaynağın sadece "resmi" temsili . Ancak, böyle bir yardımcı uç noktasının gerçekten RESTful olup olmadığını bilmiyorum (bu yüzden sorunun başlığına "can" yazdım. Elbette teknik olarak mümkün, ama iyi bir fikir olup olmadığını bilmiyorum).

Ne düşünüyorsun? Başka olasılıklar var mı?


Foo ve Bar arasındaki ilişkinin terimi nedir? Bar'ın Foo'nun bir ebeveyni olduğunu söyleyebilir misiniz?
Nathan Merrill

A Bar, a ile ilişkilendirilmeden var olamaz Foo. Ancak, yukarıda yazdığım gibi, birden çok Fookişinin aynı şeyi paylaşması mümkündür Bar. FooBir Barilişkili olmadan bir oluşturmak mümkün olmalıdır , bu yüzden Barebeveyn olarak ele alınması gerektiğini düşünmüyorum .
ceran

1
Sana URI'lerinin doğrudan etki alanı modeli ilişkileri çevirme ve eşitlenerek oldu sorunlardan bazılarını yaşıyorsanız düşünüyorum kaynaklar için alan kişiler . REST API'lerinin hipermetin güdümlü olması ilginç olabilir . 4. noktaya özel dikkat
Laiv

Yanıtlar:


6

Bir seviye 3 REST API size döneceğini Fooilgili belirten ve aynı zamanda bir bağlantı Bar.

GET /foo/123
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456"/>
</foo>

Daha sonra API'nıza bağlantılarda gezinmeyi sağlayan bir "ayrıntıya inme" özelliği ekleyebilirsiniz;

GET /foo/123?drilldown=bar
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456">
    <bar id="456">
      ..bar stuff...
    </bar>
  </link>
</foo>

Ayrıntıya inme özelliği, API'lerin önünde durur ve yanıtları engeller. Arayan kişiye geri cevap vermeden önce ayrıntılı arama yapar ve ayrıntıları doldurur.

Çok yavaş http üzerinden istemci / sunucu sohbetini azaltır gibi bu seviye 3 REST oldukça yaygın bir şeydir. Çalıştığım şirket tam olarak bu özelliğe sahip 3. seviye bir REST API üretiyor.

Güncelleme: Değeri için, JSON'da nasıl görünebilir. API'mız bunu böyle yapılandırır. Bağlantıların vb. Bağlantılarını çekmek için detaya ineceğinizi unutmayın.

GET /foo/123?drilldown=bar

{
  "self": {
    "type": "thing.foo",
    "uri": "/foo/123=?drilldown=bar",
    "href": "http://localhost/api/foo/123?drilldown=bar"
  },
  "links": [
    {
      "rel": "bar",
      "rev": "foo",
      "type": "thing.bar",
      "uri": "/bar/456",
      "href": "http://localhost/api/bar/456"
    }
  ],
  "_bar": [
    {
      "self": {
        "type": "thing.bar",
        "uri": "/bar/456",
        "href": "http://localhost/api/bar/456"
      },
      "links": [
        {
          ..other link..
        },
        {
          ..other link..
        }
      ]
    }
  ]
}

İlginç, zaten URI'lere sıkı bağlantı kaldırmak için hiper ortam bağlantıları / denetimleri kullanıyorum, ama çok umut verici görünüyor "matkap" fikri hakkında düşünmedim. Şu anda, kaynaklarımın her JSON temsili bir linksdizi içeriyor , her girdi bir relve bir urialana sahip bir bağlantı nesnesidir (xml örneğinize benzer). Her bağlantı nesnesine üçüncü bir alan mı eklemeliyim (örn. data)? Herhangi bir standart var mı?
ceran

Detaylandırma gerçekten bir dinlenme özelliği değil, bu yüzden hiçbir standart yok (en azından bildiğim).
Qwerky

Uygulamalarımızda kullandığım stateless.co/hal_specification.html gibi bazı önerilen standartlar vardır . Örneğinize çok yakın.
Pete Kirkham

4

Tüm sorgular% 95'i istiyorsanız Fooyanı sıra Bar, daha sonra basitçe geri içeri ait Foonesne bir istekte Foo. Sadece bir özellik bar(veya ilişki için başka bir terim) ekleyin ve Barnesneyi oraya koyun . İlişki yoksa, null kullanın.

Sanırım bunu çok düşünüyorsun :)


Bu sayıyı (% 95) bulmamalıydım, bu bir hataydı, üzgünüm. Söylemek istediğim, isteklerin büyük bir kısmının aynı anda her iki kaynakla da ilgiliydi. Ama yine de sadece ilgilenen ilgili sayıda istek var Foove her Barbiri bellekte oldukça büyük olduğundan (yaklaşık 3x-4x boyutunda Foo), Barbir istemci açıkça istemiyorsa bir geri dönmek istemiyorum .
ceran

Ne kadar büyük konuşuyoruz? Aktarım süresinde bu kadar büyük bir fark yaratacağından şüpheliyim ve hızda temiz bir API'yi tercih ediyorum
Nathan Merrill
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.