RESTful API bir şeyin yokluğunu temsil eder


18

Bir kişinin ruh hayvanını seçip seçmediğini belirlemek için bir API düşünün. Sadece sıfır veya bir ruh hayvanına sahip olabilirler.

Şu anda:

/person/{id}/selectedSpiritAnimal

bir hayvan seçtiklerinde http 200 ve {selectedAnimal:mole}

ancak seçimleri olmadığında http 404 değerini döndürür.

Bu, benim bir ruh hayvanını HTTP hatası olarak - henüz bir ruh hayvanı seçmemiş olmakla - temsil ettiğimiz için ruh hayvanımı mutsuz ediyor.

Ayrıca, bir iş olarak - erm Sprit-Animal-Hampers-R-us - birisinin ne zaman seçimi olmadığını bilmek isteriz, böylece onları isteyebiliriz.

Burada daha iyi bir yanıt var:

HTTP 200 ve {selectedAnimal:null}

hatta daha açık

HTTP 200 ve {selectedAnimal:null, spiritAnimalSelected: false}

Yoksa 404'ü iade etmek daha mı iyi? this image has not yet been uploadedÇevrimiçi olarak bir görüntüyü izlerken olduğu gibi bir 404 olurdu. 404 this person has not selected a spirit animalolabilir


Bu soru kopya olarak önerildi, ancak bu soru, uygulama URL'nin temsil ettiği değişikliğe izin vermeyecek şekilde yapılandırıldığında istenen başka bir geçerli URL'yi ele alıyor.

Halbuki burada kaynağın yokluğunun anlamlı olduğu bir kaynağı nasıl temsil ettiğine bakıyorum. Yani istemcinin URL istemesi için geçerlidir ve yanıt, bir şeyin yokluğunu temsil eden kaynağı başarıyla talep etmiş olmanızdır.

Yani bu 'iş mantığı' değil, bir şeyin yokluğunun bir anlamı olduğu bir durum (meslektaşlarımın çoğu 404'ün hala doğru olduğunu iddia ediyor olabilir) ama bunu nasıl eşleştireceğimden emin değilim spec.


Bir cevap seçmek çok zor. Buradaki ve işte devam eden görüşmelerde fikrimi defalarca değiştirdim.

Benim için buraya yerleşen şey, specin müşterinin hata yaptığı bir 4xx olduğunu söylediğidir . Bu örnekte, istemciye seçilenSpiritAnimal URL'sinden bir yanıt beklemesi söylendi, bu nedenle hata oluşmadı.

Meslektaşlarım arasındaki fikir birliği, bunun kötü bir API tasarımının belirtisi olduğudur.

Muhtemelen / person / {id} 'i talep etmemiz ve kişi için bir dizi bağlantı ilişkisi döndürmemiz daha iyi olur ... o zaman / selectedSpiritAnimal bağlantısı (bir kişinin seçimi olmadığında) verilmezse, ancak yine de 404 mantıklı. Veya kısmi yanıtlar uyguladığınızı ve / / id / {id} istemcisinin verilerin bir alt kümesini istemediği sürece daha eksiksiz bir belge döndürmesine izin verdiğinizde


5
Neden 404 döndürmenin bir sorun olduğuna inandığınızı açıklamıyorsunuz. Etki alanı açısından, istemci katmanı tarafından soyutlanan bir 404 veya 200 alıp almadığınızı bilmiyorsunuz.
Vincent Savard

14
ya da 204 içerik içermemesi daha iyidir?
Paul D'Ambra

6
Sanırım 404 ile olan endişem, ruh hayvanı olmayan bir kişiden kötü bir URL şablonu getiren bir yapılandırma değişikliğini belirsizleştiriyor
Paul D'Ambra

2
@ PaulD'Ambra Değeri için hiçbir içerik kullanmazdım. XmlHttpRequest günlerinden bu yana Javascript'te ön uçta işlenen HTTP kodlarını görmedim. Ama kesinlikle geçerli.
Brandon Arnold

Yanıtlar:


24

HTTP 4xx kodları muhtemelen bu senaryo için doğru seçim değildir. Sıfır ruhlu hayvanlara sahip olmanın geçerli bir durum olduğunu ve API yolunun person/{id}/selectedSpiritAnimalkişinin idsahip olup olmadığını hesaba katacağını belirtirsiniz .

HTTP 4xx yanıtları, bir istemcinin istekte yanlış bir şey yaptığı durum için ayrılmıştır (bkz. W3'ün orijinal teknik özellikler arşivi ). Ancak müşteri, idbir ruh hayvanına sahip olsun ya da olmasın, geçerli bir talepte bulunmaktadır .

Bu nedenle, yanıtta düzgün biçimlendirilmiş bir JSON gövdesi ve bir HTTP 2xx kodu kullanarak ikinci çözümlere yaslanıyorum.

Şimdi böyle bir istek alırsanız ve bu kişinin olmadığı ortaya çıkarsa id, 4xx kodu daha mantıklıdır.


17
"HTTP 4xx yanıtları, istemcinin istekte yanlış bir şey yapması durumunda ayrılmıştır". Spesifikasyon hakkında yetkili ifadeler yaparken, lütfen (a) üzerine inşa edilmiş bir çerçeve veya (b) rastgele bir blog yazısı değil, gerçek HTTP spesifikasyonuna bakın.
Eric Stein

5
@EricStein Bu konuda biraz tembel hissettim; eleştiri için teşekkürler. Güncellenmiş.
Brandon Arnold

1
Buradaki RFC bağlantısı biraz çelişkili gibi hissediyorum. Bir yandan 4xx kısmı söylüyor cases in which the client seems to have erred, diğer yandan 404 doğrudan söylüyor The server has not found anything matching the Request-URI. İstemci hatası olmayan bir şey istemeyi düşünebilirsiniz. Mevcut olmayan bir alt pervane vs olmayan kişiyi anlıyorum, ancak bu yanıt mesajı olarak belirtilebilir. 204, varlık mevcut olduğundan, ancak bir alt mülk için içeriğe sahip olmadığından da alakalı görünmektedir.
shortstuffsushi

1
Müşteri yanlış bir şey yaptı; seçili ruh hayvanından bir kullanıcı olmadığında talep etti. 404 tam olarak bunun anlamı ... orada olmayan bir şey istedin.
Andy

5
Tarayıcım softwareengineering.stackexchange.com/questions/unicorn için bir istekte bulunduğunda, bu geçerli bir istek ve yine de bir 404 alıyorum ("tek boynuzlu at" kimliğiyle ilgili hiçbir soru olmayacak).
user253751

24

Size Richardson Olgunluk Modeli'ni tanıtayım .

Sorununuz, hiper-medya ile gösterilen bir ilişkiye sahip iki kaynağınızın olması gereken iki kaynağı bir olarak temsil etmenizdir. İlişkileri tanımlamak için hipermedya kullanmak, Rest'in görkemli seviye 3'üdür.

Kişiniz URI altında yaşamalıdır /person/{id} ve hayvan altında yaşamalıdır /spiritanimal/{id}. Kişi, hayvana bir bağlantı kullanarak ruh hayvanına sahip olduğunu belirtmelidir.

Haydi Bob adında bir kimliği ve bir Unicorn ruhu hayvanı olan bir insan düşünelim.

GET /person/123

dönecekti;

{
  "name": "Bob",
  "links": [
    {
      "rel": "spiritanimal",
      "uri": "/spiritanimals/789"
    }
  ]
}

Şimdi, 123 kişisini okuyan herkes, bir ruh hayvanına sahip olduğunu ve daha fazla bilgi edinebilecekleri URI'ye sahip olduğunu bilecektir.

GET /spitiranimal/789

geri dönebilir

{
  "type": "Unicorn"
}

Şimdi Fred adında, 456 numaralı kimliği olan ve ruhu hayvanı olmayan bir insan düşünelim.

GET /person/456

dönecekti;

{
  "name": "Fred",
  "links": [
  ]
}

Şimdi 456 kişisini okuyan herkes, hiçbir ruh hayvanının olmadığını, bağlantı olmadığı için bilecektir. İlişki eksikliğini göstermek için herhangi bir HTTP durum kodu kullanmaya gerek yoktur.


1
Sadece api değiştirme yeteneği göz önüne alındığında, bazı HATEOAS seviyelerinin muhtemelen doğru çözüm olacağını soruyordum. Bu harika bir örnek
Paul D'Ambra

1

Bu, ruh hayvanlarını almak için uygun url'dir; bu nedenle, 404 hatası uygun değildir. 404 mantık problemi değil, teknik problemi temsil etmek içindir.

Uygun çözüm http 200 ve {"selectedAnimal": null}

Geri dönen ayrı bir web metodunuz olmalıdır . Perde arkasında, aynı yöntem çağrıları yapılabilir veya yapılmayabilir, sadece null olursa yanlış döndürülür, ancak tüketen kod değil karar vermesi gerekir./person/{id}/hasSelectedSpiritAnimal{"isSpiritAnimalSelected": false}

Sorguları yakından ilişkili olsa bile, zorlayıcı bir neden olmadan ayrı sorguları tek bir web yönteminde birleştirmekten kaçınmak daha iyidir.


1
Bunun neden uygun çözüm olduğuna inandığınızı açıklayabilir misiniz? Döndürülecek veri olmadığında veri döndürmenin bir anlamı olamaz. 404'ün URL iyi olduğu için bir anlam ifade etmediğini kabul ediyorum, bu yüzden 204 benim için en anlamlı gibi görünüyor.
Vincent Savard

2
@VincentSavard Durum kodlarıyla çalışmak json yanıtlarından daha zordur ve alan adı bilgilerini iletmektense teknik konular için daha uygundur.
TheCatWhisperer

2
204: Boş gövdeli içerik yok . Her şey açık ve kendini açıklayıcı. Daha fazla tartışmaya gerek yok. Sonuç olarak, net bir tasarım deseni olmadığında, bir SE bir tane seçmeli, ihtiyacına göre bükmeli ve dokümantasyon sağlamalıdır. 204 yanıtı olan bir gövdeyi döndürmek bir sonuç değildir.
formixian

2
@formixian ... json / http yerine bjson / tcp api oluşturuyorsanız, bu durum için ne döndürürdünüz? Http kodlarına güvenmek bana api sonuçlarını gereksiz yere http uygulamasına bağlamak gibi görünüyor.
TheCatWhisperer

2
@VincentSavard When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"İçerik olmaması, içerik olmaması anlamına gelir . yani: "" döndürür. Bu ikisi birbirine hiç benzemiyor. "ruh hayvan şu anda dosyada değil" "" den çok farklı.
Shane

1

Son noktanızın temsil ettiği sadece bir hayvan değildir; bu bir hayvan ya da yokluğu. En iyi Optional/ Maybe/ Nullable/ vb. İle temsil edilen bir değerdir .

Bu nedenle geçerli değerler (200 OK'deki gibi) olabilir:

  • {'animal': <some animal>, 'selected': true}
  • {'animal': null, 'selected': false}

Bunu hayal olabilir DELETEbitiş noktasına uygulandığında yöntemini ayarlayabilirsiniz 'selected'için falseolduğunu, seçilen hayvan unset, yine.

Tabii ki, 'selected'anahtarı buraya bırakabilirsiniz , sadece netlik için gösterilir; string vs nullayrım için yeterlidir.


0

404 kullanmalısınız.

404 (Bulunamadı) durum kodu, kaynak sunucunun hedef kaynak için geçerli bir temsil bulamadığını gösterir

RFC7231

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

"mole"

HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Mon, 25 Sep 2017 00:00:00 GMT

this person has not selected a spirit animal

Bir insan arabirimi değil, bir programlama arabirimi yaptığınız için, 404 metni isteğe bağlıdır.

Bunu tercih ederim çünkü standart protokolleri mümkün olduğunca tercih ederim. HTTP'nin var olmayanları temsil etmenin bir yolu vardır ve ben de bunu kullanırım.

EDIT: Kullanıcıların ruh hayvanlarını paylaşıp paylaşmayacaklarını seçebildikleri ve birisinin paylaşmadığı bir özellik eklediğinizi varsayalım. 200 OK nullveya 200 OK döndürür müsünüz "Unauthorized? Yoksa standart 401 Yetkisiz / 403 Yasak'ı kullanır mısınız? Bu, ilk etapta birini seçmemeye doğrudan benziyor.


Alternatif olarak, 200 OK + JSON kullanmak istiyorsanız, geri dönmelisiniz null.

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

"mole"

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

null

Her şeyi temiz tutun. Yalnızca gerekirse daha fazla sargı oluşturun.


2
Veri edilir olsa da, bulunan. Sadece verilerin null(değeri olmayan) olduğu görülür . Bu, değeri tutacak bir yuva bulunmayan bir şey isteyen istemciden farklıdır. AttributeErrorDeğer olduğunda Python'a atmayı önermezsiniz None; arayüzün pratik ve gereksiz yere çalışılmasını zorlaştıracaktır. Daha pragmatik olarak, birçok HTTP istemci API'si 404'ü dilin standart hata işleme mekanizmasına (hata kodu, istisna, hata türü) dönüştürebilir, yani fazladan bir hatayı bastırmanız gerekir.
jpmc26

@ Paul Draper Spesifikasyonda biraz yukarı kaydırın, HTTP 4xx hakkında battaniye bir açıklama yaptığını göreceksiniz: "4xx durum kodu sınıfı, istemcinin hata yaptığı durumlar için tasarlanmıştır." Operasyon, bir ruh hayvanına sahip olmamanın, API'nin hesaba katması gereken geçerli bir durum olduğunu açıkça belirtti. tools.ietf.org/html/rfc7231#section-6.5
Brandon Arnold

Öyleyse, istenen kaynağın var olmadığını (yani seçilen hayvan yok) ve geçersiz bir yol isteyen istemciyi (yani /person/{id}/selectedSpritAnimal, yazım hatasını gözlemleyin Sprit) nasıl ayırt edersiniz ?
sampathsris

1
Niyetinden bağımsız olarak, 404 kesinlikle kaynağın bulunmadığı anlamına gelir. SelectedSpiritAnimal bir kaynaksa ve hiçbiri yoksa, GET için hiçbir şey yoktur ve 404 uygundur. Ancak, müşteri bir ruh hayvanının seçilip seçilmediğini bilmek istiyorsa, sunucu /person/{id}/isSpiritAnimalSelectedistemciye seçilip seçilmediğini söyleyecek başka bir kaynak ortaya koymalıdır . Bana bir dosyanın okunmadan önce var olup olmadığını test etmenin aynı klasik örneğini görünüyor. Sadece dosyayı okuyun ve atılırsa ENOENT hatasını ele alın.
aaaaaa

1
@PaulDraper Nokta kaynağın var olup olmadığı değil. Buradaki nokta HTTP 4xx kodları, arayanın API'yı yanlış kullandığında kullanılması içindir. Op /person/{id}/selectedSpiritAnimal, ruh hayvanı olmasa bile kullanılması gerektiğini belirtir . Bu, HTTP 4xx'in böyle bir durumda kullanıldığında yanlış olduğu anlamına gelir. Op ayrıca bunun kötü API tasarımı kokusu olabileceğini de doğru bir şekilde belirtiyor.
Brandon Arnold
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.