Haruskah saya menggunakan kode status HTTP untuk menjelaskan acara tingkat aplikasi

54

Beberapa server yang telah saya tangani akan mengembalikan HTTP 200 untuk permintaan yang seharusnya dianggap gagal oleh klien, dengan sesuatu seperti 'sukses: salah' di dalam tubuh.

Ini sepertinya bukan implementasi kode HTTP yang tepat bagi saya, terutama dalam kasus otentikasi gagal. Saya telah membaca kode kesalahan HTTP dengan ringkas yang diringkas sebagai, '4xx' menunjukkan bahwa permintaan tidak boleh dibuat lagi sampai diubah, sementara '5xx' menunjukkan bahwa permintaan mungkin atau mungkin tidak valid dan dapat dicoba kembali, tetapi tidak berhasil. Dalam hal ini 200: gagal masuk, atau 200: tidak dapat menemukan file itu, atau 200: tidak ada parameter x, pasti tampak salah.

Di sisi lain, saya bisa melihat argumen yang dibuat bahwa '4xx' seharusnya hanya mengindikasikan masalah struktural dengan permintaan. Sehingga layak untuk mengembalikan 200: pengguna / kata sandi buruk daripada 401 tidak sah karena klien diizinkan untuk membuat permintaan, tetapi itu ternyata tidak benar. Argumen ini dapat diringkas sebagai, jika server dapat memproses permintaan dan membuat keputusan sama sekali, kode respons seharusnya 200, dan terserah klien untuk memeriksa isi informasi lebih lanjut.

Pada dasarnya, ini sepertinya masalah pilihan. Tapi itu tidak memuaskan, jadi jika ada yang punya alasan mengapa salah satu dari paradigma ini lebih benar, saya ingin tahu.

Kagan Mattson
sumber
9
success: falsemenyiratkan bahwa permintaan gagal dan Anda mengetahuinya. Seharusnya 500. Sesuatu seperti nama pengguna / kata sandi Anda yang buruk akan menjadi 401. Ini tidak ambigu.
Pete
4
Ini adalah salah satu pertanyaan yang bisa memicu perang agama. Untuk RESTful API, jawabannya jelas, tetapi ada jenis-jenis API lain di mana HTTP diperlakukan hanya sebagai lapisan transport, dan dalam kasus-kasus itu, kesalahan aplikasi tidak boleh berdarah ke lapisan itu.
Gort the Robot
5
Ketika saya benar-benar tidak yakin apa status http untuk dikembalikan, selalu tergoda untuk menggunakan 418 "Saya seorang teko."
joshp
1
Contohnya adalah beberapa (batch) permintaan dan tanggapan . Batching bukanlah hal yang tenang; tetapi masalah efisiensi praktis sering membutuhkan beberapa dukungan untuk mengatasi masalah keanggunan.
rwong

Jawaban:

35

Pertanyaan menarik.

Pada dasarnya, kita dapat mengurangi ini ke cara yang benar untuk mengklasifikasikan hal-hal dalam hal analog dengan lapisan OSI. HTTP umumnya didefinisikan sebagai protokol Tingkat Aplikasi, dan HTTP memang merupakan protokol Klien / Server generik.

Namun, dalam praktiknya, server hampir selalu merupakan perangkat relai, dan klien adalah browser web, yang bertanggung jawab untuk menafsirkan dan merender konten: Server hanya meneruskan hal-hal ke aplikasi sewenang-wenang, dan bahwa aplikasi mengirimkan kembali skrip sewenang-wenang yang oleh browser bertanggung jawab untuk mengeksekusi. Interaksi HTTP itu sendiri - formulir permintaan / respons, kode status, dan sebagainya - sebagian besar merupakan urusan bagaimana meminta, melayani, dan membuat konten sewenang-wenang seefisien mungkin, tanpa menghalangi. Banyak kode status dan tajuk memang dirancang untuk tujuan ini.

Masalah dengan mencoba membonceng protokol HTTP untuk menangani aliran spesifik aplikasi, adalah Anda hanya memiliki satu dari dua opsi: 1) Anda harus menjadikan logika permintaan / respons Anda sebagai bagian dari aturan HTTP; atau 2) Anda harus menggunakan kembali aturan tertentu, dan kemudian pemisahan kekhawatiran cenderung menjadi kabur. Ini bisa terlihat bagus dan bersih pada awalnya, tapi saya pikir itu salah satu keputusan desain yang akhirnya Anda sesali ketika proyek Anda berkembang.

Oleh karena itu, saya akan mengatakan lebih baik untuk secara eksplisit tentang pemisahan protokol. Biarkan server HTTP dan web browser melakukan hal mereka sendiri, dan membiarkan aplikasi melakukan nya hal sendiri. Aplikasi ini harus dapat membuat permintaan, dan perlu tanggapan - dan logikanya tentang cara meminta, bagaimana menafsirkan tanggapan, bisa lebih (atau kurang) kompleks daripada perspektif HTTP.

Manfaat lain dari pendekatan ini, yang perlu disebutkan, adalah bahwa aplikasi harus, secara umum, tidak tergantung pada protokol transportasi yang mendasarinya (dari sudut pandang logis). HTTP itu sendiri telah berubah di masa lalu, dan sekarang kita memiliki HTTP 2 kicking, mengikuti SPDY. Jika Anda melihat aplikasi Anda tidak lebih dari sebuah plugin fungsionalitas HTTP, Anda mungkin akan terjebak di sana ketika infrastruktur baru mengambil alih.

Yam Marcovic
sumber
8
Sangat mendalam. Argumen terkuat di sini adalah ketidakcocokan (impedansi) antara kode status HTTP dan nilai pengembalian aplikasi Anda. Ini bisa menjadi mimpi buruk dalam jangka panjang. Lebih lanjut, saya sangat mendukung pemisahan kekhawatiran antara transportasi (HTTP) dan muatan (data aplikasi). Jika Anda salah ketik URL titik akhir layanan, Anda mendapatkan 404. Jika Anda meminta layanan untuk item yang tidak ada, Anda mendapatkan pesan khusus aplikasi (mungkin dengan informasi tambahan yang dapat Anda gunakan untuk menyelesaikan masalah).
2
Jika Anda salah ketik URL, Anda mungkin tidak berakhir di server yang tepat, dan kemudian apa pun bisa terjadi.
gnasher729
Ini adalah tampilan yang bernuansa baik. Saya pikir masalah HTTP menjadi lapisan pseudo-transport adalah masalah nyata dengan membuat tekad. Saya paling sering mengalami pertanyaan ini sendiri ketika Anda memiliki server nginx atau apache proksi server nodejs, di mana proxy sudah memiliki aturan untuk mengirim kode-kode ini, dan pertanyaannya menjadi apakah layak bagi backend untuk menyesuaikan dengan standar. Dalam beberapa kasus mungkin ada alasan desain untuk tidak mengirim kode kesalahan, karena nginx dapat menafsirkannya sebagai 'backend down.'
Kagan Mattson
4
Saya setuju. Tidak ada yang salah dengan kesalahan lapisan aplikasi yang dilaporkan dalam respons HTTP 200. Angka 200 menunjukkan bahwa permintaan / respons HTTP itu sendiri berhasil, tanpa mengatakan apa-apa tentang kontennya atau semantik lapisan aplikasi yang dipanggil pada saat itu.
Lightness Races with Monica
22

Pertanyaan ini sedikit berdasarkan pendapat, tapi bagaimanapun juga.

Cara saya melihatnya, 200 dapat melayani "kesalahan lunak". Ketika datang untuk membangun API, saya mencoba untuk membedakan antara ini dan "kesalahan keras".

"Kesalahan lunak" akan disajikan dengan kode status 200, tetapi akan berisi deskripsi kesalahan dan status keberhasilan false. "Kesalahan lunak" hanya akan terjadi ketika hasilnya "seperti yang diharapkan", tetapi tidak berhasil dalam arti yang paling ketat.

Penting untuk dicatat bahwa "kesalahan lunak" lebih merupakan petunjuk bagi pelaksana. Oleh karena itu penting juga untuk memberikan informasi lebih lanjut tentang kesalahan seperti pesan kesalahan yang dapat dibaca manusia dan / atau semacam kode yang dapat digunakan untuk memberikan umpan balik kepada pengguna akhir. Kesalahan ini memberikan pelaksana (dan pengguna akhir) informasi lebih lanjut tentang apa yang terjadi di sisi server .

Misalnya, Anda memiliki API dengan fungsi pencarian tetapi selama pencarian, tidak ada hasil yang dihasilkan. Ini tidak keliru, tetapi juga bukan "sukses", tidak dalam pengertian definisi yang paling ketat.

Contoh diformat sebagai JSON:

{
    "meta" {
        "success": false,
        "message": "Search yielded no results",
        "code": "NORESULTS"
    }
    "data": []
}

"Hard error" di sisi lain, akan disajikan dengan kode status yang direkomendasikan untuk kesalahan tersebut. Pengguna tidak masuk? - 403 / 401. Input tidak benar? - 400. Kesalahan server? - 50X. Dan seterusnya.

Sekali lagi, ini sedikit berdasarkan opini. Beberapa orang ingin memperlakukan semua kesalahan sama, "kesalahan keras" semuanya. Tidak ada hasil pencarian? Itu 404! Di sisi lain dari koin, tidak ada hasil pencarian? - Ini seperti yang diharapkan, tidak ada kesalahan.

Faktor lain yang penting untuk dipertimbangkan adalah arsitektur Anda, misalnya; jika Anda berinteraksi dengan API Anda menggunakan permintaan JavaScript XHR dan jQuery atau AngularJS. "Kesalahan keras" ini harus ditangani dengan callback terpisah, sedangkan "kesalahan lunak" dapat ditangani dengan "keberhasilan" -callback. Tidak melanggar apa pun, hasilnya masih "seperti yang diharapkan". Kode sisi klien kemudian dapat melihat status-sukses dan kode (atau pesan). Dan cetak itu ke pengguna akhir.

mati maus
sumber
2
Sebenarnya, mengklasifikasikan itu sebagai kesalahan pada level API sama sekali adalah keputusan yang aneh. Meskipun klien dapat, atas kebijakannya, mengklasifikasikannya sebagai tidak terduga pada tingkat pengguna.
Deduplicator
1
Ada banyak hal yang harus diperhitungkan. Itu semua tergantung pada implementasi API. Itu juga lagi, sedikit berbasis opini dan juga turun ke apa yang didefinisikan oleh API sebagai "sukses" dan / atau "kesalahan". The "success": false-flag lebih dari petunjuk kepada pelaksana bahwa sesuatu terserah. Biasanya harus dengan kode status internal . Entah "code": "NORESULTS"atau kode numerik - apa pun yang diciptakan pembuat API. Sebagian besar ada di sana sehingga siapa pun yang mengimplementasikan API dapat mengurangi informasi tentang apa yang terjadi di server.
die maus
15

Ada dua aspek API: Upaya mengimplementasikan API, dan upaya semua klien untuk menggunakan API dengan benar.

Sebagai penulis klien, saya tahu bahwa ketika saya mengirim permintaan ke server web, saya mungkin mendapatkan kesalahan (tidak pernah berbicara dengan benar ke server), atau balasan dengan kode status. Saya harus menangani kesalahan. Saya harus menangani respons yang baik. Saya harus menangani tanggapan yang diharapkan, didokumentasikan, "buruk". Saya harus menangani apa pun yang kembali.

Merancang API, Anda harus melihat apa yang paling mudah bagi klien untuk diproses. Jika klien mengirim permintaan yang terbentuk dengan baik, dan Anda dapat melakukan apa yang diminta oleh Anda, maka Anda harus memberikan jawaban dalam kisaran 200 (ada beberapa kasus di mana angka selain 200 dalam kisaran itu sesuai).

Jika klien bertanya "berikan saya semua catatan seperti ...", dan ada nol, maka 200 dengan sukses dan array nol catatan sepenuhnya sesuai. Kasus-kasus yang Anda sebutkan:

"Login gagal" biasanya seharusnya 401. "Tidak dapat menemukan file" harus 404. "Parameter yang hilang x" harus sekitar 500 (sebenarnya, 400 jika server mengetahui bahwa permintaannya buruk, dan 500 jika server benar-benar bingung dengan permintaan saya dan tidak tahu apa yang sedang terjadi). Mengembalikan 200 dalam kasus ini tidak ada gunanya. Itu hanya berarti sebagai penulis klien, saya tidak bisa hanya melihat kode status, saya harus mempelajari jawabannya juga. Saya tidak bisa mengatakan "status 200, bagus, ini datanya".

Terutama "parameter yang hilang" - itu bukan sesuatu yang akan pernah saya tangani . Itu berarti permintaan saya salah. Jika permintaan saya salah, saya tidak memiliki cadangan untuk memperbaiki permintaan yang salah - Saya akan mengirim permintaan yang benar untuk memulai. Sekarang saya terpaksa menanganinya. Saya mendapatkan 200 dan harus memeriksa apakah ada balasan "parameter hilang". Itu sangat buruk.

Pada akhirnya, ada selusin atau dua kode status untuk menangani berbagai situasi yang berbeda, dan Anda harus menggunakannya.

gnasher729
sumber
3
Saat menghubungkan ke API, saya pribadi lebih suka mendapatkan 200 pada 'file tidak ditemukan' saat menghubungkan ke titik akhir yang valid, karena penanganan HTTP saya tidak harus berdarah ke lapisan yang menangani API di atasnya.
whatsisname
4
"Parameter yang hilang x" harus menjadi 400 BAD_REQUEST karena klien melakukan sesuatu yang salah. 500 INTERNAL_SERVER_ERROR harus dicadangkan untuk kasus-kasus di mana server melakukan hal yang salah. A 500 menyiratkan bahwa klien mungkin dapat mencoba lagi. A 400 menyiratkan bahwa seseorang harus memperbaiki klien.
Gort the Robot
1
Jika Anda menulis antarmuka RESTful, URL mengidentifikasi objek tertentu sehingga 404 sesuai. Secara konseptual, hal yang sama /customers/premium/johndoe.jsonmengacu pada pelanggan yang tidak ada dalam database dan jika /files/morefiles/customers.htmlmerujuk ke halaman yang tidak ada di sistem file.
Gort the Robot
@whatsisname Apa yang Anda katakan masuk akal karena dengan demikian tidak jelas apakah itu titik akhir yang buruk atau sumber daya tidak ada. Anda juga dapat berdebat bahwa apakah titik akhir itu valid atau tidak, tidak ada sumber daya di alamat itu sehingga 404benar dalam kedua kasus.
Pete
2
Satu hal yang belum saya lihat disebutkan adalah bahwa ketika Anda membonceng kesalahan aplikasi ke kode status HTTP, Anda mungkin kehilangan informasi. Jika aplikasi hanya mengembalikan 404 dan tidak ada yang lain, Anda tidak tahu apakah itu karena API Anda mengembalikan 404, atau karena server tidak dapat menemukan file. Itu bisa menambahkan satu langkah ekstra untuk debugging Anda.
AmadeusDrZaius