Haruskah "Tidak Ada Hasil" menjadi kesalahan dalam respons RESTful?

52

Saya akan menjelaskan sebuah contoh:
Saya mulai membuat API untuk toko kue. API akan memungkinkan orang untuk mencari catalogus mereka untuk membuat produk kue, seperti cookie chocolate chip buatan sendiri api.examplebakery.com/search?q=......

Seseorang menggunakan ini untuk mencari produk bernama pineapple-banana flavoured cookiesdan jelas tidak akan menemukan hasil.

Haruskah ini dikembalikan sebagai kesalahan? Pencarian tidak gagal, API mencari dan berhasil menyimpulkan tidak ada cookie yang dapat ditemukan. API tidak boleh kembali 404, karena memang API itu ditemukan.

Berry M.
sumber
6
Kemungkinan duplikat API TENANG mewakili tidak adanya sesuatu
agas
3
@gnat: Ini bukan duplikat, karena pertanyaan lain adalah tentang sumber daya tertentu, bukan kueri terhadap beberapa sumber daya.
Greg Burghardt
7
Secara analog, misalkan Anda memiliki fungsi yang mengembalikan array objek. Jika tidak ada objek yang cocok dengan use case tertentu, apakah Anda lebih suka fungsinya melalui pengecualian atau mengembalikan array kosong?
Kevin - Reinstate Monica
2
@ AashashM Mengembalikan HTTP-204 ke permintaan GET sangat tidak biasa, saya tahu saya belum pernah melihatnya di mana pun. Sejauh yang saya tahu, HTTP-204 biasanya digunakan sebagai respons ketika memodifikasi sumber daya di server, misalnya permintaan POST / PUT / DELETE.
Radu Murzea

Jawaban:

122

Ketika ada hasil, hasilnya adalah daftar (JSON, berdasarkan komentar Anda). Untuk pertanyaan tanpa hasil, output harus persis sama. Daftar sederhana memiliki 0 item di dalamnya.

Jadi jika respons Anda seperti ini:

{
    "results": [
        {
            "name": "Pancakes",
            ....
        },
        {
            "name": "French Fries",
            ....
        }
    ]
}

Maka untuk kueri dengan 0 hasil, seharusnya ini:

{
    "results": []
}

Jika Anda juga memasukkan meta data tentang berapa "halaman" hasil yang ada, tautan ke "halaman" itu, dll. Maka saya sarankan mengatakan ada 1 "halaman".

Status HTTP harus sama dengan ketika ada hasil - 200 OK.

204 No Contentmungkin juga tampaknya menjadi pilihan, tetapi itu bukan karena Anda sebenarnya mengembalikan "konten" - daftar kosong. Jika Anda merasa daftar kosong tidak dihitung sebagai "konten", bagaimana jika Anda kemudian mengubah respons untuk menawarkan saran ejaan? Inti dari respons masih akan menjadi daftar kosong, tetapi sekarang ada lebih banyak "konten".

Untuk informasi lebih berguna tentang kode status HTTP, jpmc26 jawabannya layak dibaca.

Jory Geerts
sumber
9
Ini adalah jenis pemikiran yang sama dengan pola objek nol . Kesalahan dan null bukan satu-satunya cara untuk mengatakan tidak ada apa pun di sini. Terkadang Anda ingin mengekspresikan apa pun dengan diam-diam. Dengan begitu klien tidak perlu menguji apa pun.
candied_orange
54
Saya berpendapat bahwa mengembalikan 204 tidak pantas, karena Anda mengembalikan konten. Hanya saja konten tidak memiliki hasil, yang berbeda dari tidak mengembalikan konten sama sekali.
TMN
9
@TMN setuju - 204 tidak sesuai untuk "tidak ada hasil." Kueri Anda harus selalu mengembalikan array, dengan hasil di dalam array. Jika tidak ada hasil, klien akan menanganinya secara alami. Jika klien ingin menampilkan teks khusus ("Tidak ada hasil ditemukan"), maka itu tidak masalah. 204 seharusnya hanya dikembalikan untuk titik akhir yang tidak secara alami mengembalikan hasil.
JasonB
1
Anda dapat menggunakan 204 jika Anda mengembalikan null yang diserialisasi sebagai string kosong yang saya rekomendasikan
Ewan
15
Ini. Yang penting ketika membangun API Tenang adalah bagian API, bukan restfullness. API yang baik membuat hidup lebih mudah bagi klien / konsumen. Array kosong lebih mudah ditangani daripada nilai null / pengecualian / kode status.
Guran
37

Setiap kali memutuskan kode HTTP, Anda harus selalu menanyakan pertanyaan ini:

Apa yang bisa / akan / harus dilakukan klien sewenang-wenang dengan respons?

  1. Haruskah klien selalu memperlakukan respons sebagai kegagalan? Maka Anda ingin 4xx atau 5xx, tergantung pada apakah masalahnya adalah input klien atau proses server.
  2. Haruskah klien membuat permintaan di tempat lain saja? Maka 3xx adalah untuk Anda.
  3. Apakah server melakukan apa yang diminta klien (berhasil)? Itu 2xx.

Selalu tentukan kisaran kode respons Anda yang seharusnya berada di urutan pertama. Melakukannya dengan cepat menghilangkan banyak kode respons sebagai opsi, dan (mungkin lebih penting) membuatnya mengikuti semantik kode menjadi lebih sederhana. Lihat bagian awal dokumentasi kode HTTP untuk penjelasan tentang apa yang diwakili oleh setiap kategori kode.

Dalam kasus ini, klien meminta daftar hasil yang diberikan filter dari titik akhir yang valid dan sudah ada dan memiliki izin untuk mengaksesnya. Server dapat memproses permintaan dan menentukan data yang sesuai untuk dikembalikan (tanpa item), sehingga permintaan berhasil. Kebetulan filter yang mereka berikan menyaring semua hasil. Tidak tergantung pada server untuk menentukan apakah ini yang diinginkan klien atau tidak, karena ini mungkin hasil yang diharapkan untuk beberapa klien. Jika ini merupakan masalah bagi kode klien, itu adalah tanggung jawab klien untuk menentukan, memeriksa, dan menangani dengan tepat. Jadi ini jelas 2xx.

Sekarang pertanyaannya adalah, "2xx yang mana?" Ini tergantung pada bagaimana Anda ingin server merespons.

  • Apakah Anda akan mengirim kembali representasi daftar kosong, seperti dijelaskan oleh jawaban lain ? Jika demikian, Anda ingin 200. 200 berarti server tidak mengalami masalah dan memiliki representasi hasil yang akan dikonsumsi klien. Ini mungkin cara yang paling mudah untuk merespons bagi konsumen Anda, yang hanya dapat menguraikan respons apakah ada hasil atau tidak dan kemudian mencari tahu bagaimana menangani daftar kosong sendiri.
  • 204 tidak secara semantik salah di sini, tetapi Anda harus merespons tanpa pesan apa pun . Ini berarti semua kode klien harus secara eksplisit memeriksa kode HTTP yang berbeda (atau setidaknya karena kurangnya badan pesan) dan menanganinya secara terpisah. Ini tidak nyaman dan lebih cenderung mengarah pada klien yang berperilaku buruk.

Yang lain tidak berlaku sama sekali:

  • 201 keluar dari pertanyaan. Anda tidak membuat sumber daya terus-menerus dan tidak mengembalikan lokasi ke sumber daya yang dibuat.
  • 202 keluar dari pertanyaan. Permintaan dilakukan; itu tidak diproses di latar belakang.
  • 203 berarti bahwa respons telah dimodifikasi antara server otoritatif dan klien. Antarmuka RESTful Anda adalah server otoritatif, jadi ini tidak berlaku di sini.
  • 205 tidak masuk akal. Anda tidak perlu klien untuk menghapus atau menyegarkan apa pun.
  • 206 tampaknya dirancang untuk mengembalikan sumber daya yang besar melalui beberapa respons. Ini juga mensyaratkan bahwa klien meminta bagian dari konten di header (jadi pagination melalui string kueri tidak memenuhi syarat). Tidak berlaku di sini.

Jadi itu harus 200 atau 204, dan 200 lebih cenderung mengarah pada kode klien yang lebih sederhana dan lebih kuat (terutama jika Anda menggunakan struktur respons yang konsisten yang berisi daftar kosong).

jpmc26
sumber
5
Akan tertarik dengan pendapat downvoter. Saya pikir semua ini tidak kontroversial.
jpmc26
2
Saya tidak berpikir klien harus memeriksa 204 secara eksplisit. Yang mereka butuhkan adalah kemampuan untuk menangani objek respons nol. Adalah tugas kerangka HTTP untuk menangani 204 dengan melewatkan bagian "parse the body". 200 dengan Content-Panjang 4 dan tubuh nol sama saja.
Agent_L
1
@ Agg_L Anda benar bahwa jika server merespons dengan struktur tidak konsisten dengan respons normal (seperti menempatkan di nullmana biasanya ada daftar), Anda tidak akan menuai manfaat konsistensi bahkan dengan 200. Namun, apa yang saya jelaskan menggunakan respons yang konsisten dengan struktur normal dan memiliki daftar kosong tempat daftar hasil biasanya pergi. 204 mengambil setiap peluang untuk mendapat tanggapan yang konsisten. Juga, bahkan di pustaka klien HTTP yang memiliki fungsi kenyamanan untuk itu, Anda sering (biasanya?) Harus membuat panggilan eksplisit untuk mem-parse JSON.
jpmc26
@ Agg_L Khususnya dengan daftar, penelepon sering dapat membiarkan kode mereka berjalan secara normal di atas daftar kosong (misalnya, dengan memutarnya,), sedangkan mereka memerlukan semacam pemeriksaan eksplisit untuk menangani jenis representasi lainnya.
jpmc26
16

Tidak. Penggunaan 404 untuk menunjukkan 'permintaan Anda diproses tetapi tidak ada kecocokan' mengerikan karena:

  • aliran bersyarat berdasarkan penanganan pengecualian (mis. memaksa hasil yang tidak luar biasa untuk membuat dan menangani pengecualian pada klien yang dapat menjadi tidak berkinerja dan canggung)

  • ambiguitas antara halaman 'nyata' tidak ditemukan, Anda mengetik kesalahan titik akhir salah

Yang perlu diingat adalah bahwa selalu ada klien untuk membatalkan deserialisasi pesan dan apa yang dikembalikan oleh klien itu penting; bukan serialisasi.

Jika klien harus mengembalikan nol, maka gunakan serialisasi dari nol. Jika klien harus mengembalikan array kosong, gunakan [], jika klien harus melempar kesalahan gunakan 500 dan sampaikan pesan kesalahan

Ewan
sumber
2
Mengapa server harus peduli dengan apa yang klien lakukan dengan informasi itu? (PS: Bukan saya yang menurunkan jawaban Anda).
Radu Murzea
dalam konteks ini 'klien' adalah kode yang berjalan pada perangkat klien yang memaparkan layanan ke aplikasi klien. Itu harus dapat memaparkan metode layanan dan mengembalikan hasil sebagaimana dimaksud oleh layanan. Anda memerlukan pasangan klien-server agar komunikasi berfungsi sama sekali
Ewan
3
Jangan gunakan 5xx untuk kesalahan klien , tentu saja. Lebih suka 4xx dalam kasus itu.
Kevin
1
Meskipun, bukankah seharusnya itu "server", bukan "klien" di sebagian besar contoh ini? Server yang memproses permintaan dan melayani respons, klien hanya memproses respons? Dalam hal mana kode 5xx akan baik-baik saja, karena ini merupakan kesalahan server, bukan kesalahan klien?
MrWhite
2
masalah dengan semua kode kesalahan adalah bahwa mereka memiliki makna di dalam http. 500 adalah satu-satunya kode yang cocok untuk ketika layanan Anda melempar pengecualian
Ewan
9

Beyond @ Ewan jawaban yang sangat bagus:

Jika kueri adalah jenis yang mengembalikan set hasil, maka set kosong secara logis sama layaknya dengan set satu, atau set lebih banyak. Secara umum untuk alasan yang menyatakan @wan, tidak ada salahnya lebih baik untuk mengubah set kosong menjadi kesalahan, dan, itu sama sekali tidak perlu.

Jika kueri adalah jenis yang mencari dan mengembalikan singleton spesifik (yang diharapkan akan ditemukan, misalnya kecocokan dengan id), maka tidak ditemukan adalah respons yang mungkin secara logis sesuai.

Erik Eidt
sumber
ya saya benar-benar memikirkan itu pada jawaban Ewan.
Walfrat
5

Anda mengasumsikan kode harus mengambil tindakan khusus ketika tidak ada data yang dikembalikan, tetapi itu mungkin tidak terjadi. Kode mungkin hanya mencari jumlah produk, atau menambahkan hasilnya ke daftar atau sejumlah hal. Anda seharusnya hanya memberi "kesalahan" kepada pengguna jika sebenarnya ada kesalahan.

John Smith
sumber
3
"Anda seharusnya hanya memberi" kesalahan "kepada pengguna jika sebenarnya ada kesalahan." - ini. Hasil kosong yang ditetapkan saat melakukan "pencarian" biasanya bukan "kesalahan". Namun, jika koneksi database gagal yang berarti pencarian tidak dapat benar-benar dilakukan maka hasil yang kosong ditetapkan (dan tidak ada kesalahan) jika tidak akan ambigu. Beberapa jenis kesalahan akan sesuai dalam kasus ini (mungkin bersama-sama dengan hasil kosong yang ditetapkan - tergantung pada bagaimana API didefinisikan).
MrWhite
0

Ketika saya menggunakan API, sebagai klien saya harus menangani kasus "sukses" berbeda dari kasus "kesalahan"; Saya tidak punya pilihan di sana. Oleh karena itu, Anda harus mengembalikan kesalahan dalam situasi yang ingin diperlakukan berbeda oleh klien , dan sukses dalam situasi yang ingin diperlakukan sama oleh klien .

Jika saya melakukan kueri yang secara teori dapat mengembalikan sejumlah hasil, nol, satu, dua ratus dan seterusnya, maka Anda harus mengembalikan "sukses" setiap kali API memberikan daftar lengkap semua hasil. Dan mungkin dalam kasus di mana ada banyak hasil, Anda mengembalikan sebagian daftar hasil untuk menghindari ukuran yang berlebihan, dan ada cara yang disepakati bagaimana saya akan mendapatkan hasil lainnya. Itu karena sebagai klien, saya sering ingin menangani kasus hasil nol seperti kasus hasil lebih banyak. Saya mungkin memperlakukannya secara berbeda, tetapi saya tidak mau dipaksa.

Ini berbeda dalam hal saya mencari nilai. Saya mengharapkan satu hasil, nilai yang saya cari. Dan saya membutuhkan satu hasil untuk melanjutkan apa yang ingin saya lakukan dengan cara yang bermakna. Di sini jauh lebih dapat diterima untuk mengembalikan status 404 untuk kasus yang tidak ada nilainya di sana, karena saya memang perlu menangani kasus itu secara berbeda.

Ringkasan: Jika klien mengharapkan sejumlah hasil, dari nol hingga jumlah besar, maka kembalikan "sukses" jika semua hasil dikirimkan, bahkan jika jumlahnya nol. Jika klien mengharapkan tepat satu hasil, maka kembalikan sukses jika hasilnya ditemukan, dan kesalahan jika hasilnya tidak ditemukan.

gnasher729
sumber