REST API error mengembalikan praktik yang baik [ditutup]

623

Saya mencari panduan tentang praktik yang baik untuk mengembalikan kesalahan dari REST API. Saya sedang mengerjakan API baru sehingga saya bisa mengambil arah apa pun sekarang. Jenis konten saya adalah XML saat ini, tetapi saya berencana untuk mendukung JSON di masa depan.

Saya sekarang menambahkan beberapa kasus kesalahan, seperti misalnya klien mencoba menambahkan sumber daya baru tetapi telah melebihi kuota penyimpanannya. Saya sudah menangani kasus kesalahan tertentu dengan kode status HTTP (401 untuk otentikasi, 403 untuk otorisasi dan 404 untuk URI permintaan buruk). Saya melihat-lihat kode kesalahan HTTP yang diberkati, tetapi tak satu pun dari kisaran 400-417 yang tampaknya benar untuk melaporkan kesalahan spesifik aplikasi. Jadi pada awalnya saya tergoda untuk mengembalikan kesalahan aplikasi saya dengan 200 OK dan payload XML tertentu (mis. Bayar kami lebih banyak dan Anda akan mendapatkan penyimpanan yang Anda butuhkan!) Tapi saya berhenti untuk memikirkannya dan sepertinya berbusa (/ mengangkat bahu ngeri). Selain itu rasanya seperti saya memecah tanggapan kesalahan menjadi kasus yang berbeda, karena beberapa kode status http didorong dan lainnya didorong oleh konten.

Jadi apa rekomendasi industri? Praktik yang baik (tolong jelaskan alasannya!) Dan juga, dari pov klien, penanganan kesalahan seperti apa di API REST yang mempermudah kode klien?

Remus Rusanu
sumber
7
Hanya untuk mengklarifikasi: Saya tidak begitu tertarik pada kode status HTTP mana yang akan dikembalikan, tetapi apakah praktik REST yang baik untuk menggabungkan kesalahan muatan dengan kode status HTTP atau lebih baik hanya mengandalkan muatan itu.
Remus Rusanu
3
Buku Pegangan Desain API REST membahas topik ini dengan cukup baik.
Remus Rusanu
12
Pertanyaannya tidak meminta pendapat, tetapi untuk panduan / rekomendasi dan harus dibuka kembali dan digunakan sebagai referensi. Apa gunanya menutup pertanyaan pada tahun 2016, yang dibuat pada tahun 2009, memiliki 400+ suara dan tidak ada jawaban yang ada berdasarkan pendapat
Michael Freidgeim
4
Sebagian besar tidak menyebutkan, tetapi menggunakan kode kesalahan HTTP dapat menyebabkan masalah terkait penyebab utama masalah. HTTP adalah protokol transport dan 404 harus mengindikasikan, bahwa ada masalah dengan level transport URLon (misal jalur yang salah). Jika aplikasi tidak dapat menemukan dataset dengan idnya, ini adalah kesalahan level aplikasi (bukan kesalahan level transportasi) dan 404, seperti yang disarankan oleh pengguna kode status http yang tenang, dapat mengarah pada kesimpulan yang salah. Secara umum saya tidak suka campuran transport dan lapisan aplikasi dalam menggunakan kode status.
SCI

Jawaban:

220

Jadi pada awalnya saya tergoda untuk mengembalikan kesalahan aplikasi saya dengan 200 OK dan payload XML tertentu (mis. Bayar kami lebih banyak dan Anda akan mendapatkan penyimpanan yang Anda butuhkan!) Tapi saya berhenti untuk memikirkannya dan sepertinya berbusa (/ mengangkat bahu ngeri).

Saya tidak akan mengembalikan 200 kecuali benar-benar tidak ada yang salah dengan permintaan tersebut. Dari RFC2616 , 200 berarti "permintaan telah berhasil."

Jika kuota penyimpanan klien telah terlampaui (untuk alasan apa pun), saya akan mengembalikan 403 (Terlarang):

Server mengerti permintaan itu, tetapi menolak untuk memenuhinya. Otorisasi tidak akan membantu dan permintaan TIDAK HARUS diulang. Jika metode permintaan itu bukan KEPALA dan server ingin mengumumkan kepada publik mengapa permintaan itu belum dipenuhi, itu HARUS menggambarkan alasan penolakan di entitas. Jika server tidak ingin membuat informasi ini tersedia untuk klien, kode status 404 (Tidak Ditemukan) dapat digunakan sebagai gantinya.

Ini memberi tahu klien bahwa permintaan itu OK, tetapi gagal (sesuatu yang tidak dilakukan oleh 200). Ini juga memberi Anda kesempatan untuk menjelaskan masalah (dan solusinya) di badan respons.

Apa kondisi kesalahan spesifik lainnya yang ada dalam pikiran Anda?

Apodaca kaya
sumber
6
Haruskah saya memasukkan pesan kesalahan rinci saya dalam tubuh, yaitu. pasangan kode XML / string? Bagaimana klien terbaik menangani ini? Misalnya saya tahu klien berbasis C # WebRequest akan melempar 'Permintaan Buruk' atau 'Terlarang' dan tidak memberikan tanggapan.
Remus Rusanu
18
Tubuh 403 "harus" berisi rincian kesalahan. Apakah klien siap memanfaatkan informasi itu adalah cerita lain. Masuk akal untuk format ini sama dengan format untuk semua muatan lainnya (misalnya, XML, JSON).
Rich Apodaca
1
... dan jika detailnya tidak dikembalikan di 403, 404 "bisa" digunakan sebagai gantinya (tidak terdengar seperti pilihan terbaik bagi saya).
Rich Apodaca
6
Opsi 404 adalah untuk acara yang 403 mungkin mengungkapkan rincian tentang aplikasi yang Anda tidak ingin tahu tentang pengguna tidak sah - jika pengguna non-administratif menyentuh URL khusus admin, misalnya, Anda mungkin tidak ingin pengguna itu untuk mengetahui bahwa itu adalah URL yang valid untuk admin, dll. Namun, dalam kasus ini, 403 sepenuhnya tepat.
Greg Campbell
16
Saya merasa ini adalah jawaban yang sangat tidak membantu. Saya akan berpikir aspek yang lebih penting adalah mengenai apakah status harus digunakan semata-mata, atau apakah informasi kesalahan harus dikembalikan dalam muatan, atau keduanya, dll. Dan kemudian BAGAIMANA informasi tersebut harus ditambahkan dalam muatan. Status spesifik yang digunakan adalah mengasah hanya pada satu aspek spesifik dari pertanyaan.
Manachi
584

Sumber yang bagus untuk memilih kode kesalahan HTTP yang benar untuk API Anda: http://www.codetinkerer.com/2015/12/12/choosing-an-http-status-code.html

Kutipan dari artikel:

Mulai dari mana:

masukkan deskripsi gambar di sini

2XX / 3XX:

masukkan deskripsi gambar di sini

4XX:

masukkan deskripsi gambar di sini

5XX:

masukkan deskripsi gambar di sini

Omar Ali
sumber
1
422 Adalah ekstensi WebDAV khusus. Saya pikir itu seharusnya tidak ada di sini.
Mario
@Mario Adalah idiomatis di Ruby on Rails API untuk mengembalikan 422 sebagai respons terhadap kondisi yang ditentukan di sini. Banyak yang baik mengikuti pendekatan itu. Untuk apa Anda mengganti penggunaan 422?
Kelsey Hannan
400 tua biasa
Andbdrew
Terima kasih. Apa artinya "Apakah Anda mengamuk-berhenti dari Internet?"
RoutesMaps.com
@ Crimean.us google.com/search?q=define+rage-quit
Omar Ali
87

Pilihan utama adalah apakah Anda ingin memperlakukan kode status HTTP sebagai bagian dari REST API Anda atau tidak.

Keduanya bekerja dengan baik. Saya setuju bahwa, sebenarnya, salah satu ide REST adalah Anda harus menggunakan kode Status HTTP sebagai bagian dari API Anda (mengembalikan 200 atau 201 untuk operasi yang sukses dan 4xx atau 5xx tergantung pada berbagai kasus kesalahan.) Namun , tidak ada polisi ISTIRAHAT. Anda dapat melakukan apa yang Anda inginkan. Saya telah melihat API non-REST jauh lebih mengerikan disebut "TENANG."

Pada titik ini (Agustus, 2015) saya merekomendasikan Anda menggunakan kode Status HTTP sebagai bagian dari API Anda. Sekarang jauh lebih mudah untuk melihat kode kembali ketika menggunakan kerangka kerja daripada sebelumnya. Secara khusus, sekarang lebih mudah untuk melihat kasus pengembalian non-200 dan badan tanggapan non-200 daripada di masa lalu.

Kode Status HTTP adalah bagian dari api Anda

  1. Anda harus hati-hati memilih kode 4xx yang sesuai dengan kondisi kesalahan Anda. Anda dapat memasukkan pesan istirahat, xml, atau plaintext sebagai payload yang mencakup sub-kode dan komentar deskriptif.

  2. Klien harus menggunakan kerangka kerja perangkat lunak yang memungkinkan mereka untuk mendapatkan kode status tingkat HTTP. Biasanya bisa dilakukan, tidak selalu lurus ke depan.

  3. Klien harus membedakan antara kode status HTTP yang menunjukkan kesalahan komunikasi dan kode status Anda sendiri yang menunjukkan masalah tingkat aplikasi.

Kode Status HTTP BUKAN bagian dari api Anda

  1. Kode status HTTP akan selalu 200 jika aplikasi Anda menerima permintaan dan kemudian merespons (baik kasus sukses maupun kesalahan)

  2. SEMUA respons Anda harus menyertakan informasi "amplop" atau "header". Biasanya sesuatu seperti:

    envelope_ver: 1.0
    status: # gunakan kode yang Anda suka. Cadangan kode untuk sukses.
    msgstr "String manusia yang mencerminkan kode. Berguna untuk debugging.
    data: ... # Data respons, jika ada.
  3. Metode ini dapat lebih mudah bagi klien karena status respons selalu di tempat yang sama (tidak perlu sub-kode), tidak ada batasan pada kode, tidak perlu mengambil kode status tingkat HTTP.

Berikut ini postingan dengan ide serupa: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Masalah utama:

  1. Pastikan untuk memasukkan nomor versi sehingga nanti Anda dapat mengubah semantik api jika diperlukan.

  2. Dokumen...

Larry K
sumber
8
Ty. Opsi 2 tampaknya seperti SOAP dalam pakaian sisa meskipun ...
Remus Rusanu
138
Tidak, menerobos semuanya melalui 200 tidak tenang sama sekali. Ini mencegah perantara dari memahami hasil operasi, yang akan membunuh segala bentuk caching, menyembunyikan semantik operasi, dan memaksakan memahami isi pesan untuk memproses kesalahan, melanggar batasan pesan mandiri.
SerialSeb
13
Mengembalikan detail kesalahan dengan angka 200 mungkin tidak TETAP, tetapi ini adalah jawaban yang berguna (jika Anda mengabaikan komentar "Kedua cara ini tenang") ... Poin yang lebih besar mungkin bahwa RESTful API mungkin bukan pilihan terbaik untuk OP.
MB.
3
Tampaknya ada pemahaman umum bahwa Anda dapat melakukan apa pun yang Anda inginkan dengan protokol HTTP dan masih "RESTY", itu salah. Gunakan protokol untuk apa yang ditulisnya, itulah salah satu ide inti dari REST. Jadi kode status harus menjadi bagian dari protokol Anda.
Ariel M.
Inti dari kode status adalah untuk menyediakan bahasa umum pemahaman antara beragam bahasa pemrograman, kerangka kerja dan pendekatan. Makna kode status hampir universal: badan khusus Anda - yang secara inheren menambah lebih banyak kerumitan melalui sintaks khusus yang harus dipelajari oleh konsumen API Anda - tidak.
Kelsey Hannan
40

Ingat ada lebih banyak kode status daripada yang didefinisikan dalam HTTP / 1.1 RFCs, registri IANA ada di http://www.iana.org/assignments/http-status-codes . Untuk kasus yang Anda sebutkan kode status 507 terdengar benar.

Julian Reschke
sumber
3
Hmm, sementara sekilas "507 Insufficient Storage" sepertinya itu mungkin tepat, saya akan ragu menggunakannya karena itu dimaksudkan sebagai ekstensi WebDAV (cukup spesifik) dan bukan umum "hei Anda keluar dari ruang" pengecualian. Tetap saja, saya kira Anda bisa menggunakannya.
Maks
1
Tidak, ini sama sekali tidak spesifik untuk WebDAV. Ada alasan mengapa ada registri untuk kode status HTTP.
Julian Reschke
26
Saya tidak setuju dengan 507tujuan ini. Interpretasi saya 507adalah bahwa server kehabisan ruang, bukan karena akun itu kehabisan ruang.
Patrick
12
Saya setuju dengan Patrick. 5xxkesalahan adalah kesalahan yang harus dilakukan dengan server.
Sean
10
418: "Saya seorang teko" yang menyiratkan bahwa ruang penyimpanan terlalu sedikit (seperti teko sedikit) daripada besar dan dengan demikian keluar dari ruang.
Steve Konves
22

Seperti yang telah ditunjukkan orang lain, memiliki entitas respons dalam kode kesalahan sangat diijinkan.

Ingat bahwa kesalahan 5xx adalah sisi-server, alias klien tidak dapat mengubah apa pun pada permintaannya untuk membuat permintaan lolos. Jika kuota klien terlampaui, itu jelas bukan kesalahan server, jadi 5xx harus dihindari.

SerialSeb
sumber
Saya tidak akan setuju. Kuota Melebihi akan menjadi kesalahan server (5xx) karena: Permintaan klien valid dan akan berhasil jika di bawah kuota, yang mengesampingkan 400series.
mikek3332002
4
Tetapi server tidak melakukan kesalahan.
Charlie Schliesser
19

Ada dua macam kesalahan. Kesalahan aplikasi dan kesalahan HTTP. Kesalahan HTTP hanya untuk memberi tahu penangan AJAX Anda bahwa segalanya berjalan dengan baik dan tidak boleh digunakan untuk hal lain.

5xx server error

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx Sukses

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Namun, bagaimana Anda merancang kesalahan aplikasi Anda benar-benar terserah Anda. Stack Overflow misalnya mengirimkan objek dengan response, datadan messageproperti. Respons yang saya yakini berisi trueatau falseuntuk menunjukkan apakah operasi itu berhasil (biasanya untuk operasi tulis). Data berisi muatan (biasanya untuk operasi baca) dan pesan berisi metadata tambahan atau pesan berguna (seperti pesan kesalahan saat responseada false).

aleemb
sumber
2
400 juga bermanfaat untuk menunjukkan masalah dalam aplikasi klien.
dolmen
19

Saya tahu ini sangat terlambat untuk pesta, tetapi sekarang, pada tahun 2013, kami memiliki beberapa jenis media untuk meliput penanganan kesalahan dengan cara yang umum didistribusikan (ISTIMEWA). Lihat "vnd.error", application / vnd.error + json ( https://github.com/blongden/vnd.error ) dan "Detail Masalah untuk API HTTP", aplikasi / masalah + json ( https: // alat. ietf.org/html/draft-nottingham-http-problem-05 ).

Jørn Wildt
sumber
2
Terima kasih atas tautannya. draft-nottingham-http-problem sekarang menjadi standar yang diusulkan: datatracker.ietf.org/doc/rfc7807
seanf
9

Sepakat. Filosofi dasar REST adalah menggunakan infrastruktur web. Kode Status HTTP adalah kerangka kerja pengiriman pesan yang memungkinkan para pihak untuk berkomunikasi satu sama lain tanpa menambah muatan HTTP. Mereka sudah menetapkan kode universal yang menyampaikan status respons, dan oleh karena itu, untuk benar-benar tenang, aplikasi harus menggunakan kerangka kerja ini untuk mengkomunikasikan status respons.

Mengirim respons kesalahan dalam amplop HTTP 200 menyesatkan, dan memaksa klien (api konsumen) untuk mem-parsing pesan, kemungkinan besar dengan cara non-standar, atau berpemilik. Ini juga tidak efisien - Anda akan memaksa klien Anda untuk mengurai payload HTTP setiap saat untuk memahami status respons "nyata". Ini meningkatkan pemrosesan, menambah latensi, dan menciptakan lingkungan bagi klien untuk melakukan kesalahan.

Kingz
sumber
3
Apakah Anda memiliki respons yang berhasil, atau respons yang gagal, Anda kemungkinan besar akan menguraikan respons tersebut. Jika itu adalah kesalahan, Anda ingin menguraikannya untuk mengeluarkan pesan kesalahan. Respons kesalahan umumnya kecil dan cepat untuk diuraikan. Saya tidak berpikir kita harus khawatir tentang mencoba mengoptimalkan untuk menghindari parsing tanggapan kesalahan. Apakah Anda hanya membuang respons kesalahan tanpa menguraikannya? Tidak bijak menurut saya.
AgilePro
3
Jika Anda mendapatkan 200 OK, Anda dapat memilih untuk tidak menguraikannya juga, tergantung pada aturan bisnis Anda. Intinya bukan apakah kita menguraikannya setiap saat atau tidak. Intinya adalah niat - apa maksud dari 200 OK? Anda merusak maksud dengan mengirim pesan kesalahan yang dibungkus dalam 200 OK.
Kingz
1
"Apa maksud dari 200 OK?" - menunjukkan keberhasilan lapisan transport. Permintaan telah berhasil diterima dan dijawab, hanya ada masalah khusus aplikasi yang tidak ada hubungannya dengan HTTP. +++ Letakkan sebaliknya, Mengirim 404 di dunia REST berarti sesuatu tidak ditemukan, mungkin URL salah atau sumber daya yang akan diproses atau yang lainnya tidak ditemukan. Tanpa menguraikan pesan, Anda tidak bisa. IMHO ISTIRAHAT hanya menyatukan lapisan.
maaartinus
Konflasi adalah norma. Ini memberi Anda sintaks untuk berurusan dengan yang sesuai dengan garis penalaran Anda, dan membebaskan Anda untuk fokus pada lapisan bisnis. Menyetujui pengangkutan kemudian status comm - itulah tujuan awalnya - REST tidak ditemukan / diusulkan secara bersamaan dengan HTTP - ia datang kemudian dan hanya memutuskan untuk menggunakan infrastruktur yang ada untuk mewakili STATES dan PERUBAHAN mereka.
Kingz
5

Harap tetap menggunakan semantik protokol. Gunakan 2xx untuk respons yang berhasil dan 4xx, 5xx untuk respons kesalahan - baik itu pengecualian bisnis Anda atau lainnya. Seandainya menggunakan 2xx untuk respons apa pun adalah kasus penggunaan yang dimaksudkan dalam protokol, mereka tidak akan memiliki kode status lainnya.

rahil008
sumber
3

Jangan lupa kesalahan 5xx juga untuk kesalahan aplikasi.

Dalam hal ini bagaimana dengan 409 (Konflik)? Ini mengasumsikan bahwa pengguna dapat memperbaiki masalah dengan menghapus sumber daya yang tersimpan.

Kalau tidak 507 (tidak sepenuhnya standar) juga dapat berfungsi. Saya tidak akan menggunakan 200 kecuali jika Anda menggunakan 200 untuk kesalahan secara umum.

Kathy Van Stone
sumber
-2

Jika kuota klien terlampaui itu adalah kesalahan server, hindari 5xx dalam hal ini.

anuitas tetap
sumber
3
Mengapa menghindari kesalahan seri 5xx ketika mereka untuk kesalahan server?
mikek3332002
7
'kuota klien terlampaui' bukan merupakan kesalahan server imho, ini adalah pembatasan klien dan harus di bawah 4xx.
MyGGaN