Apa respons kode status HTTP yang sesuai untuk permintaan umum yang tidak berhasil (bukan kesalahan)?

109

Saya membuat RESTful API yang akan memproses sejumlah interaksi pengguna, termasuk melakukan pemesanan menggunakan kartu kredit yang tersimpan.

Jika pesanan berhasil, saya mengembalikan 200 OK, dan dalam kasus permintaan pesanan salah format atau tidak valid, saya mengembalikan 400 Permintaan Buruk. Tetapi apa yang harus saya kembalikan jika ada masalah selama pemrosesan pesanan yang sebenarnya?

  1. Klien POST pesanan ke server untuk sumber daya pengguna. Jika pengguna tidak ada, 404 Not Found dikembalikan.
  2. Format dan informasi pesanan divalidasi. Jika tidak valid, 400 Permintaan Buruk dikembalikan.
  3. Pesanan diproses. Jika pesanan berhasil, 201 Dibuat dikembalikan untuk pesanan. Jika terjadi kesalahan yang tidak terduga, 500 Server Error dikembalikan.

Langkah terakhir adalah masalahnya - apa yang harus saya kembalikan jika pesanan tidak selesai karena alasan lain? Skenario yang mungkin termasuk:

  • Produk sudah habis terjual
  • Batas pesanan maksimum pengguna tercapai
  • Kegagalan transaksi kartu kredit (dana tidak mencukupi, dll.)

Sepertinya ini tidak akan sesuai untuk 400 atau 500. Jika ada, saya bisa melihatnya sebagai 400 jika tidak ada kode yang lebih baik - permintaan tidak valid menurut aturan bisnis. Sepertinya tidak akurat.

Edit: Juga ditemukan diskusi yang ada tentang topik yang sama ini. Semua jawaban di sana tampaknya mengarah pada penggunaan kode status untuk jenis pelanggaran ini, dengan beberapa diskusi antara menggunakan 400, 409, atau ekstensi 422.

Raelshark
sumber
8
Saya suka '422 entitas yang tidak dapat diproses' untuk kesalahan validasi. Dan akan menggunakannya untuk contoh Anda di atas, sertakan pesan dalam tanggapan dengan masalah bisnis yang sebenarnya "Produk terjual habis" dan mungkin menambahkan 'kode' Anda sendiri jika klien perlu secara terprogram membuat keputusan yang berbeda berdasarkan tanggapan
house9
sebelum Anda beralih ke 422, pertimbangkan apakah Anda mendukung kemampuan WebDAV
Mbithy Mbithy

Jawaban:

90

Anda harus menggunakan 400 untuk aturan bisnis. Jangan mengembalikan 2xx jika pesanan tidak diterima. HTTP adalah protokol aplikasi, jangan pernah lupakan itu. Jika Anda mengembalikan 2xx, klien dapat menganggap bahwa pesanan telah diterima, terlepas dari informasi apa pun yang Anda kirim di bagian isi.


Dari Buku Resep Layanan Web RESTful :

Satu kesalahan umum yang dilakukan beberapa layanan web adalah mengembalikan kode status yang mencerminkan keberhasilan (kode status dari 200 hingga 206 dan dari 300 hingga 307) tetapi menyertakan badan pesan yang menjelaskan kondisi kesalahan. Melakukan hal ini akan mencegah perangkat lunak yang mendukung HTTP untuk mendeteksi kesalahan. Misalnya, cache akan menyimpannya sebagai respons yang berhasil dan menyajikannya ke klien berikutnya meskipun klien mungkin dapat membuat permintaan yang berhasil.

Saya akan menyerahkannya kepada Anda untuk memutuskan antara 4xx dan 5xx, tetapi Anda harus menggunakan kode status kesalahan.

Max Toro
sumber
1
Apakah Anda memiliki contoh atau referensi untuk pendekatan ini dibandingkan yang lain? Jawaban Anda dan Widor masuk akal, satu dari perspektif HTTP sebagai protokol aplikasi, dan yang lainnya karena hanya untuk tujuan transfer. Spesifikasi mendefinisikannya sebagai "protokol level aplikasi", yang agak kabur. Saya juga telah melihat perspektif dan contoh di seluruh web saat meneliti ini.
Raelshark
ini sangat benar.
Young Hyun Yoo
2
Apakah maksud Anda, 'Anda harus menggunakan 4xx untuk aturan bisnis'?
Yawar
28

Anda harus menggunakan 4xx untuk kesalahan klien jika klien dapat mengubah permintaan untuk mengatasi kesalahan tersebut. Gunakan 5xx untuk kesalahan server yang tidak dapat diatasi oleh klien.

Produk terjual habis akan menjadi kesalahan server. Klien tidak dapat mengubah permintaan dengan cara tertentu untuk mengatasi kesalahan. Anda dapat beralih ke produk lain tetapi bukankah itu permintaan baru?

Batas pesanan maksimum pengguna tercapai juga merupakan kesalahan server. Tidak ada yang dapat dilakukan klien untuk mengatasi kesalahan itu.

Kegagalan transaksi kartu kredit akan menjadi kesalahan klien. Klien dapat mengirim ulang permintaan dengan metode pembayaran atau nomor kartu kredit yang berbeda untuk mengatasi kesalahan tersebut.

Paul Morgan
sumber
6
Jika batas pesanan tercapai, bukankah seharusnya klien memberi tahu pengguna tentang hal itu dan membiarkan mereka mengubah permintaannya dengan tepat? Sepertinya kesalahan 4xx. Hal yang sama berlaku untuk produk yang terjual habis. Kesalahan 5xx dimaksudkan untuk kesalahan yang disebabkan oleh kerusakan sistem dalam beberapa cara, bukan untuk tindakan yang tidak diizinkan oleh aturan bisnis.
carlin.scott
7
Saya setuju dengan komentar di atas. Kesalahan 5xx untuk saat server mengalami masalah. 4xx kesalahan untuk aturan bisnis.
Merc
21

Jenis kesalahan:

4×× Client Error

Kode kesalahan:

422 Unprocessable Entity

Server memahami tipe konten dari entitas permintaan (oleh karena itu kode status Jenis Media yang Tidak Didukung 415 tidak sesuai), dan sintaks dari entitas permintaan benar (dengan demikian kode status Permintaan Buruk 400 tidak sesuai) tetapi tidak dapat memproses yang terkandung instruksi.

Misalnya, kondisi kesalahan ini dapat terjadi jika isi permintaan XML berisi instruksi XML yang dibentuk dengan baik (yaitu, benar secara sintaksis), tetapi salah secara semantik, instruksi XML.

https://httpstatuses.com/422

stamster
sumber
16

Saya tahu pertanyaan ini sudah tua, tetapi saya datang dengan pertanyaan yang sama hari ini. Jika pengguna saya kehabisan kredit, kode status apa yang harus dikembalikan REST API saya?

Saya cenderung condong ke arah 402 Payment Required:

Menurut Wikipedia :

Dicadangkan untuk penggunaan di masa mendatang. Maksud awalnya adalah bahwa kode ini dapat digunakan sebagai bagian dari beberapa bentuk tunai digital atau skema pembayaran mikro, tetapi itu tidak terjadi, dan kode ini biasanya tidak digunakan. Google Developers API menggunakan status ini jika pengembang tertentu telah melebihi batas harian permintaan.

Dan memang mereka melakukannya :

PAYMENT_REQUIRED (402)

  • Batas anggaran harian yang ditetapkan oleh pengembang telah tercapai.
  • Operasi yang diminta membutuhkan lebih banyak sumber daya daripada yang diizinkan oleh kuota. Pembayaran diperlukan untuk menyelesaikan operasi.
  • Operasi yang diminta membutuhkan semacam pembayaran dari pengguna yang diautentikasi.
Benjamin
sumber
Ini adalah jawaban yang paling dipikirkan dan logis.
GTodorov
5

Bagaimana dengan 424 Failed Dependency? Spesifikasi menggambarkannya sebagai:

Metode ini tidak dapat dijalankan pada sumber daya karena tindakan yang diminta bergantung pada tindakan lain dan tindakan itu gagal.

Tetapi ada juga definisi ini :

Kode status 424 ditentukan dalam standar WebDAV dan untuk kasus di mana klien perlu mengubah apa yang dilakukannya - server tidak mengalami masalah apa pun di sini.

Anda dapat memberi tahu klien (atau berpura-pura) bahwa Anda memiliki tindakan internal yang seharusnya membuat pesanan, dan mengurangi saldo, dan bahwa salah satu tindakan tersebut gagal, meskipun untuk alasan yang benar-benar valid, dan itulah mengapa permintaan gagal.

Sejauh yang saya lihat, "tindakan" adalah istilah yang cukup luas, dan dapat digunakan dalam berbagai situasi, termasuk stok tidak mencukupi, kredit tidak mencukupi, atau pesta gudang di malam hari.


Pilihan lain mungkin 422 Unprocessable Entity:

Server memahami tipe konten dari entitas permintaan (oleh karena itu kode status Jenis Media yang Tidak Didukung 415 tidak sesuai), dan sintaks dari entitas permintaan benar (dengan demikian kode status Permintaan Buruk 400 tidak sesuai) tetapi tidak dapat memproses yang terkandung instruksi.

Misalnya, kondisi kesalahan ini dapat terjadi jika isi permintaan XML berisi instruksi XML yang dibentuk dengan baik (yaitu, benar secara sintaksis), tetapi salah secara semantik, instruksi XML.

Mencoba meminta item yang stoknya habis, atau saat kredit Anda tidak mencukupi, dapat dianggap sebagai kesalahan pada tingkat semantik.

MozDev mengatakan ini menunjukkan kesalahan di sisi klien, khususnya: Klien tidak boleh mengulangi permintaan ini tanpa modifikasi.

Loopback 4 menggunakan 422 ketika validasi input gagal.


Bisa dibilang, stok yang tidak mencukupi atau malam pesta gudang bisa dianggap status sementara, jadi permintaan bisa dicoba lagi nanti. Situasi itu bisa ditunjukkan dengan503 Service Unavailable

Server saat ini tidak dapat menangani permintaan karena kelebihan beban sementara atau pemeliharaan terjadwal, yang kemungkinan akan diatasi setelah beberapa penundaan.

Server MUNGKIN mengirim bidang tajuk Coba-Setelah untuk menyarankan jumlah waktu yang tepat bagi klien untuk menunggu sebelum mencoba kembali permintaan.

joeytwiddle
sumber
Tak satu pun dari itu terkait dengan pembayaran. Saya menggunakan 402 dari jawaban sebelumnya!
GTodorov
2

Saya tidak berpikir 400 dapat digunakan untuk semua skenario bisnis. Ini dapat digunakan untuk validasi input data dasar. Selain itu, kami mungkin akan kesulitan menyesuaikan logika bisnis lain ke dalam kode kesalahan ini. Kesalahan yang ditangani oleh ini sebagian besar adalah kesalahan waktu desain yang mungkin ditemui pengembang selama pengkodean klien.

Katakanlah semua parameter sudah benar dan katakanlah kita memasukkan nomor akun pengguna ke dalam permintaan.

Jadi permintaan sekarang bukan lagi permintaan yang buruk, server dapat menerima permintaan tersebut. Tetapi sekarang menolak untuk memenuhi permintaan berdasarkan informasi baru yang tersedia yaitu - saldo akun tidak mencukupi.

Saya menyarankan kita harus menggunakan 403 dengan pesan kesalahan yang sesuai dalam skenario tersebut.

Kode kesalahan lain yang mungkin bisa menjadi konflik 409. Tapi itu digunakan dalam skenario di mana sumber daya dalam keadaan konsisten.

Rajender Saini
sumber
-1

Saya pergi dengan 406 Not Acceptable.

Berikut daftar 4xx:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585
Mahmoud Zalt
sumber
8
Meskipun nama kode status 406 mungkin terdengar akurat dengan sendirinya, Anda perlu mengetahui bahwa setiap kode status memiliki deskripsi tekstual yang berwibawa. Deskripsi untuk kode status 406 tidak sesuai untuk kasus yang dihadapi. Lihat httpstatuses.com/406 , misalnya.
Zero3
1
@ Zero3 benar, kode ini berarti jenis respons tidak dapat diterima, karena ada ketidakcocokan antara Header Terima yang dikirim dari klien dan MediaType yang dikirim oleh titik akhir, misalnya application / json vs. teks / biasa
Gregor