API TENANG mewakili tidak adanya sesuatu

18

Bayangkan sebuah API untuk mengidentifikasi apakah seseorang telah memilih hewan roh mereka. Mereka hanya dapat memiliki nol atau satu binatang roh.

Saat ini:

/person/{id}/selectedSpiritAnimal

ketika mereka telah memilih binatang, kembalikan http 200 dan {selectedAnimal:mole}

tetapi ketika mereka tidak memiliki pilihan itu mengembalikan http 404.

Ini membuat hewan roh saya tidak bahagia karena kami mewakili masalah domain yang valid - karena belum memilih hewan roh - sebagai kesalahan HTTP.

Plus, sebagai bisnis - erm Sprit-Animal-Hampers-R-us - kami ingin tahu ketika seseorang tidak memiliki pilihan sehingga kami dapat meminta mereka.

Apa tanggapan yang lebih baik di sini:

HTTP 200 dan {selectedAnimal:null}

atau bahkan lebih eksplisit

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

Atau lebih baik mengembalikan 404? Karena seperti this image has not yet been uploadedketika melihat gambar secara online akan menjadi 404. this person has not selected a spirit animalmungkin 404


Pertanyaan ini ini telah diusulkan sebagai duplikat tetapi pertanyaan itu membahas URL yang valid yang diminta ketika aplikasi telah dikonfigurasi untuk tidak mengizinkan perubahan yang diwakili oleh URL.

Sedangkan di sini saya melihat bagaimana seseorang mewakili sumber daya di mana ketiadaan sumber daya itu bermakna. Yaitu sah bagi klien untuk meminta URL dan jawabannya adalah Anda telah berhasil meminta sumber daya yang mewakili tidak adanya sesuatu.

Jadi ini bukan 'logika bisnis' melainkan keadaan di mana ketiadaan sesuatu memiliki makna (mungkin karena banyak rekan saya berpendapat bahwa 404 masih benar) tetapi saya tidak yakin bagaimana memetakan itu ke spek.


Sangat sulit untuk memilih jawaban. Saya telah berubah pikiran beberapa kali selama pembicaraan di sini dan yang sedang berlangsung di tempat kerja.

Hal yang menentukan bagi saya di sini adalah bahwa spesifikasi mengatakan bahwa 4xx adalah ketika klien melakukan kesalahan . Dalam hal ini klien telah diberitahu untuk mengharapkan respons dari urlSpiritAnimal yang dipilih sehingga belum keliru.

Konsensus di antara rekan-rekan saya adalah bahwa ini adalah gejala dari desain API yang buruk

Mungkin akan lebih baik jika kita hanya meminta / orang / {id} dan mengembalikan seperangkat hubungan tautan untuk orang tersebut ... maka jika Anda tidak diberi tautan / terpilihSpiritAnimal (ketika seseorang tidak memiliki pilihan) tetapi Anda sebut saja demikian maka 404 masuk akal. Atau Anda menerapkan respons sebagian dan membiarkan / orang / {id} mengembalikan dokumen yang lebih lengkap kecuali klien meminta subset data

Paul D'Ambra
sumber
5
Anda belum menjelaskan mengapa Anda percaya bahwa ini merupakan masalah untuk mengembalikan 404. Dari sudut pandang domain, Anda tidak tahu apakah Anda menerima 404 atau 200, yang disarikan oleh lapisan klien.
Vincent Savard
14
atau mungkin lebih baik mengembalikan 204 tanpa isi?
Paul D'Ambra
6
Saya kira kekhawatiran saya dengan 404 adalah mengacaukan perubahan konfigurasi yang memperkenalkan template URL yang buruk dari orang yang tidak memiliki hewan roh
Paul D'Ambra
2
@ PaulD'Ambra Untuk apa nilainya, saya tidak akan menggunakan konten-no. Saya belum melihat kode HTTP ditangani di front-end seperti itu di Javascript sejak hari XmlHttpRequest. Tapi itu pasti valid.
Brandon Arnold

Jawaban:

24

Kode HTTP 4xx mungkin bukan pilihan yang tepat untuk skenario ini. Anda menyatakan bahwa tidak memiliki hewan roh nol adalah keadaan yang valid, dan rute API person/{id}/selectedSpiritAnimalakan menjelaskan apakah orang idtersebut memiliki atau tidak.

Respons HTTP 4xx dicadangkan untuk situasi ketika klien telah melakukan sesuatu yang salah dalam permintaan (lihat arsip spesifikasi asli w3 ). Tetapi klien membuat permintaan yang valid, apakah seseorang idmemiliki hewan roh atau tidak .

Jadi saya condong ke solusi kedua menggunakan tubuh JSON yang diformat dengan baik dalam respon dan kode HTTP 2xx.

Sekarang jika Anda mendapatkan permintaan seperti itu dan ternyata orang iditu tidak ada, kode 4xx lebih masuk akal.

Brandon Arnold
sumber
17
"Respons HTTP 4xx dicadangkan untuk situasi ketika klien telah melakukan sesuatu yang salah dalam permintaan". Saat membuat pernyataan otoritatif tentang spek, harap lihat spek HTTP aktual, dan bukan (a) kerangka kerja yang dibangun di atasnya, atau (b) posting blog acak.
Eric Stein
5
@ EricStein Aku memang merasa sedikit malas tentang itu; terima kasih atas kritiknya. Diperbarui.
Brandon Arnold
1
Saya merasa seperti tautan RFC di sini agak saling bertentangan. Di satu sisi bagian 4xx mengatakan cases in which the client seems to have erred, tetapi di sisi lain 404 langsung mengatakan The server has not found anything matching the Request-URI. Anda dapat mempertimbangkan meminta sesuatu yang tidak ada kesalahan klien. Saya mengerti orang yang tidak ada vs sub prop tidak ada, tapi itu bisa diindikasikan sebagai pesan respon. 204 juga tampaknya relevan, karena entitas itu ada, tetapi tidak memiliki konten untuk sub properti.
shortstuffsushi
1
Klien memang melakukan sesuatu yang salah; itu meminta hewan roh yang dipilih untuk pengguna ketika itu tidak ada. Itulah yang dimaksud 404 ... Anda telah meminta sesuatu yang tidak ada.
Andy
5
Ketika browser saya membuat permintaan ke softwareengineering.stackexchange.com/questions/unicorn itu adalah permintaan yang valid dan saya masih mendapatkan 404 (kebetulan tidak ada pertanyaan dengan ID "unicorn").
user253751
24

Izinkan saya memperkenalkan Anda kepada Model Kematangan Richardson .

Masalah Anda adalah bahwa Anda mewakili dua sumber daya sebagai satu, di mana Anda harus benar-benar memiliki dua sumber daya yang memiliki hubungan yang ditunjukkan oleh hypermedia. Menggunakan hypermedia untuk menggambarkan hubungan adalah level 3 Rest yang mulia.

Orang Anda harus hidup di bawah URI /person/{id}dan hewan itu harus hidup di bawah /spiritanimal/{id}. Orang tersebut harus menunjukkan bahwa ia memiliki hewan roh dengan menggunakan tautan ke hewan tersebut.

Mari kita bayangkan seseorang bernama Bob, yang memiliki id 123 dan binatang roh Unicorn.

GET /person/123

akan kembali;

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

Sekarang siapa pun yang membaca orang 123 akan tahu bahwa mereka memiliki binatang roh, dan memiliki URI di mana mereka dapat memperoleh lebih banyak informasi tentangnya.

GET /spitiranimal/789

mungkin kembali

{
  "type": "Unicorn"
}

Sekarang mari kita bayangkan seseorang bernama Fred, yang memiliki id 456 dan tidak memiliki binatang roh.

GET /person/456

akan kembali;

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

Sekarang siapa pun yang membaca orang 456 akan tahu bahwa mereka tidak memiliki binatang roh, karena tidak ada tautan. Tidak perlu menggunakan kode status HTTP untuk mewakili kurangnya hubungan.

Qwerky
sumber
1
Hanya menambah pertanyaan bahwa, mengingat kemampuan untuk mengubah api, beberapa tingkat HATEOAS mungkin akan menjadi solusi yang tepat. Itu contoh yang bagus tentang hal itu
Paul D'Ambra
1

Ini adalah url yang tepat untuk mendapatkan hewan roh; oleh karena itu, kesalahan 404 tidak pantas. 404 adalah untuk merepresentasikan masalah teknis, bukan masalah logika.

Solusi yang tepat adalah mengembalikan http 200 dan {"selectedAnimal": null}

Anda harus memiliki metode web terpisah/person/{id}/hasSelectedSpiritAnimal yang mengembalikan {"isSpiritAnimalSelected": false}. Di balik layar, mungkin atau mungkin tidak membuat panggilan metode yang sama, hanya mengembalikan false jika null, tetapi itu terserah dia yang memutuskan, bukan kode pengkonsumsi.

Lebih baik untuk menghindari menggabungkan permintaan yang terpisah menjadi satu metode web tanpa alasan kuat untuk melakukannya, bahkan jika permintaan itu terkait erat.

TheCatWhisperer
sumber
1
Bisakah Anda menjelaskan mengapa Anda yakin ini adalah solusi yang tepat? Saya tidak bisa masuk akal mengembalikan data ketika tidak ada data yang dikembalikan. Saya setuju dengan Anda bahwa 404 tidak masuk akal karena URL baik-baik saja, jadi 204 tampaknya paling masuk akal bagi saya.
Vincent Savard
2
@VincentSavard Kode status lebih sulit untuk dikerjakan daripada respons json, dan lebih sesuai untuk masalah teknis daripada mengkomunikasikan informasi domain.
TheCatWhisperer
2
204: Tidak Ada Konten dengan tubuh kosong. Semuanya jelas dan jelas. Tidak perlu berdebat lebih lanjut. Semua dalam semua, ketika tidak ada pola desain yang jelas SE harus memilih satu, tekuk itu untuk kebutuhannya dan berikan dokumentasi. Mengembalikan tubuh dengan respons 204 tidak merupakan konsekuensi.
formixian
2
@formixian ... Jika Anda membuat bjson / tcp api alih-alih json / http, apa yang akan Anda kembalikan untuk kasus ini? Mengandalkan kode http bagi saya sepertinya tidak perlu mengikat hasil api ke implementasi http-nya.
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"Tidak ada konten berarti tidak ada konten . yaitu: mengembalikan "". Keduanya sama sekali tidak mirip. "Binatang roh saat ini tidak ada dalam arsip" sangat berbeda dari "".
Shane
1

Apa yang diwakili oleh titik akhir Anda bukan hanya binatang; itu binatang atau kurang. Ini nilai terbaik yang diwakili oleh Optional/ Maybe/Nullable / dll.

Jadi nilai yang sah (seperti pada 200 OK) mungkin:

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

Saya bisa membayangkan bahwa DELETEmetode, ketika diterapkan ke titik akhir, dapat diatur 'selected'kefalse lagi, yaitu, unset hewan yang dipilih.

Anda dapat, tentu saja, menjatuhkan 'selected'kunci di sini, itu hanya ditampilkan untuk kejelasan; string vs nullsudah cukup untuk membedakannya.

9000
sumber
0

Anda harus menggunakan 404.

Kode status 404 (Tidak Ditemukan) menunjukkan bahwa server asal tidak menemukan representasi saat ini untuk sumber daya target

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

Karena Anda membuat antarmuka pemrograman, bukan antarmuka manusia, teks 404 adalah opsional.

Saya lebih suka ini karena saya lebih suka protokol standar sebanyak mungkin. HTTP memiliki cara untuk merepresentasikan non-keberadaan, dan itulah yang akan saya gunakan.

EDIT: Misalkan Anda menambahkan fitur di mana pengguna dapat memilih apakah akan membagikan hewan roh mereka, dan seseorang tidak membagikannya. Apakah Anda akan mengembalikan 200 OK null, atau 200 OK "Unauthorized? Atau apakah Anda akan menggunakan standar 401 Unauthorized / 403 Forbidden? Ini sepertinya analog dengan tidak memilih yang pertama kali.


Atau, jika Anda ingin menggunakan 200 OK + JSON, Anda harus kembali 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

Jaga kebersihan. Buat lebih banyak pembungkus hanya jika perlu.

Paul Draper
sumber
2
Namun data tersebut ditemukan. Kebetulan data tersebut null(tidak memiliki nilai). Ini berbeda dari klien yang meminta sesuatu yang tidak memiliki slot untuk menyimpan nilai. Anda tidak akan menyarankan melempar dengan AttributeErrorPython ketika nilainya terjadi None; yang akan membuat antarmuka tidak praktis dan sulit untuk dikerjakan. Lebih pragmatis, banyak klien API HTTP dapat mengubah 404 menjadi mekanisme penanganan kesalahan standar bahasa (kode kesalahan, pengecualian, jenis kesalahan), yang berarti Anda harus menekan kesalahan yang tidak berhubungan.
jpmc26
@Paul Draper Gulir sedikit ke atas dalam spec, Anda akan melihat bahwa ia membuat pernyataan selimut tentang HTTP 4xx: "Kelas kode status 4xx dimaksudkan untuk kasus-kasus di mana klien tampaknya telah melakukan kesalahan." Op telah menyatakan dengan jelas bahwa tidak memiliki hewan roh adalah keadaan yang valid yang harus diperhitungkan oleh API. tools.ietf.org/html/rfc7231#section-6.5
Brandon Arnold
Bagaimana Anda, kemudian, membedakan antara menunjukkan tidak adanya sumber daya yang diminta (yaitu tidak ada hewan yang dipilih), dan klien meminta jalur yang tidak valid (yaitu /person/{id}/selectedSpritAnimal, amati kesalahan ketik Sprit).
sampathsris
1
Terlepas dari niat, 404 berarti sumber daya tidak ditemukan. JikaSpiritAnimal yang dipilih adalah sumber daya, dan tidak ada, maka tidak ada yang DAPATKAN dan 404 sesuai. Namun jika klien ingin tahu apakah hewan roh dipilih maka server harus mengekspos sumber daya lain /person/{id}/isSpiritAnimalSelectedyang akan memberi tahu klien apakah ada yang dipilih. Menurut saya contoh klasik yang sama untuk menguji apakah suatu file ada sebelum membacanya. Baca saja file tersebut dan tangani kesalahan ENOENT jika harus dibuang.
aaaaaa
1
@ PaulDraper Intinya bukan apakah sumber daya ada atau tidak. Intinya adalah kode HTTP 4xx dimaksudkan ketika pemanggil menggunakan API secara tidak benar. Op menyatakan bahwa /person/{id}/selectedSpiritAnimalitu dimaksudkan untuk digunakan bahkan jika hewan roh tidak ada. Ini berarti bahwa HTTP 4xx salah, bila digunakan dalam kasus seperti itu. Op juga dengan benar menyatakan bahwa ini mungkin bau desain API yang buruk.
Brandon Arnold