SISA kode status HTTP untuk validasi gagal atau duplikat tidak valid

826

Saya sedang membangun aplikasi dengan API berbasis REST dan telah sampai pada titik di mana saya menentukan kode status untuk setiap permintaan.

Kode status apa yang harus saya kirim untuk permintaan yang gagal validasi atau di mana permintaan mencoba untuk menambahkan duplikat di database saya?

Saya telah melihat melalui http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html tetapi tidak satupun dari mereka tampaknya benar.

Apakah ada praktik umum saat mengirim kode status?

Alex
sumber
14
Buka httpstatus.es , Klik Kanan >> Pin Tab: P
Salman von Abbas

Jawaban:

780

Untuk kegagalan validasi input: 400 Permintaan Buruk + deskripsi opsional Anda. Ini disarankan dalam buku " RESTful Web Services ". Untuk pengiriman ganda: 409 Konflik


Perbarui Juni 2014

Spesifikasi yang relevan dulu RFC2616 , yang memberikan penggunaan 400 (Permintaan Buruk) agak sempit

Permintaan tidak dapat dipahami oleh server karena sintaksis yang salah

Jadi bisa dikatakan bahwa itu tidak pantas untuk kesalahan semantik. Tapi tidak lagi; sejak Juni 2014, standar RFC 7231 yang relevan , yang menggantikan RFC2616 sebelumnya, memberikan penggunaan 400 (Permintaan Buruk) lebih luas sebagai

server tidak dapat atau tidak akan memproses permintaan karena sesuatu yang dianggap sebagai kesalahan klien

deamon
sumber
3
Ya, badan permintaan adalah bagian dari sintaksis.
deamon
62
Permintaan yang buruk jelas merupakan respons paling umum untuk masalah seperti ini. Satu-satunya alternatif lain adalah 422 Entitas yang Tidak Dapat Diproses. Ini sebenarnya berasal dari WebDav tetapi sangat valid untuk menggunakan kembali kode status apa pun yang telah terdaftar dengan IANA.
Darrel Miller
19
Jadi, bagaimana Anda membedakan antara data yang salah yang tidak dapat diurai oleh server, dan kesalahan validasi? Seorang klien akan menangani kedua tanggapan ini dengan sangat berbeda. Untuk validasi, mereka kemungkinan akan menampilkan kesalahan kepada pengguna. Untuk "data cacat", mereka akan mencatat kesalahan sehingga bug dalam metode yang menghasilkan permintaan dapat diperbaiki.
Josh Noe
18
Saya tidak setuju dengan interpretasi Anda tentang RFC7231, meskipun menyatakan something perceived to be a client error, semua contoh yang diberikan dalam paragraf ini adalah pelanggaran protokol HTTP, bukan kesalahan logis: sintaks, framing, routing. Jadi, saya menganggap bahwa spesifikasi HTTP tidak mengizinkan 400 untuk validasi gagal pada level aplikasi.
Dima Tisnek
2
mengapa tidak menggunakan entitas 422 - Unprocessable? Tampak lebih logis bagi saya
java_geek
278
  • Validasi gagal: 403 Forbidden ("Server memahami permintaan, tetapi menolak untuk memenuhinya"). Berlawanan dengan pendapat umum, RFC2616 tidak mengatakan "403 hanya ditujukan untuk otentikasi gagal", tetapi "403: Saya tahu apa yang Anda inginkan, tetapi saya tidak akan melakukan itu". Kondisi itu mungkin atau mungkin bukan karena otentikasi.
  • Mencoba menambahkan duplikat: 409 Konflik ("Permintaan tidak dapat diselesaikan karena konflik dengan kondisi sumber daya saat ini.")

Anda harus memberikan penjelasan yang lebih rinci dalam tajuk dan / atau badan tanggapan (mis. Dengan tajuk khusus - X-Status-Reason: Validation failed).

Piskvor meninggalkan gedung
sumber
17
@deamon: Itu bukan spesifikasi, itu Wikipedia, yaitu pendapat seseorang tentang "apa arti kode status HTTP"; perhatikan bahwa halaman pada dasarnya mengatakan "ini adalah apa yang dimaksud dengan Apache dengan 403, ini adalah apa yang dimaksud dengan IIS dengan 403", dan tidak ada tempat itu merujuk pada RFC resmi. Anda tampaknya mengulangi "403 berarti apa pun yang dikatakan Apache". TIDAK. RFC yang sebenarnya (yang merupakan dokumen yang relevan, bukan implementasi Apache, bukan implementasi IIS, bukan implementasi orang lain) ada di sini: w3.org/Protocols/rfc2616/rfc2616-sec10.html
Piskvor meninggalkan gedung
57
"10.4.4 403 Dilarang Server memahami permintaan tersebut, tetapi menolak untuk memenuhinya. Otorisasi tidak akan membantu dan permintaan TIDAK HARUS diulang. Jika metode permintaan itu tidak KEPALA dan server ingin mengumumkan kepada publik mengapa permintaan tersebut belum diumumkan. telah terpenuhi, itu HARUS menggambarkan alasan penolakan dalam entitas. Jika server tidak ingin membuat informasi ini tersedia untuk klien, kode status 404 (Tidak Ditemukan) dapat digunakan sebagai gantinya. " Saya melihat tidak ada penekanan di sana ("HARUS / TIDAK HARUS" adalah kata kunci RFC 2119, bukan penekanan); itu ide Anda apa yang "dilarang" artinya, bukan RFC.
Piskvor meninggalkan gedung
10
Saya suka jawaban ini, tetapi masih melihat satu masalah kecil. Menurut spesifikasi , ketika 403 dikembalikan, "permintaan TIDAK HARUS diulang". Namun, mengembalikan 409 "hanya diperbolehkan dalam situasi di mana diharapkan pengguna mungkin dapat menyelesaikan konflik dan mengirim kembali permintaan". Dalam kasus duplikat, saya pikir 403 lebih tepat, karena Anda tidak dapat benar-benar menyelesaikan konflik (kecuali dengan menghapus contoh sumber daya sebelumnya).
pablobm
2
Untuk pesan kesalahan itu sendiri, Anda harus memodifikasi frase alasannya, jadi mengirim tajuk HTTP/1.0 403 Form validation errorsadalah cara yang paling bersih.
aleemb
6
IMO, 422 "Entitas yang Tidak Dapat Diproses" jauh lebih masuk akal. Alasan saya adalah bahwa bukan karena server menolak untuk memenuhi permintaan, itu karena server tidak dapat memenuhi permintaan.
tybro0103
225

Saya merekomendasikan kode status 422, "Entitas yang tidak dapat diproses" .

11.2. 422 Entitas yang Tidak Dapat Diproses

Kode status 422 (Entitas yang Tidak Dapat Diproses) berarti server memahami jenis konten entitas permintaan (oleh karena itu kode status 415 (Jenis Media yang Tidak Didukung) tidak pantas), dan sintaks entitas permintaan benar (dengan demikian 400 (Permintaan Buruk) ) kode status tidak pantas) tetapi tidak dapat memproses instruksi yang terkandung. Misalnya, kondisi kesalahan ini dapat terjadi jika badan permintaan XML berisi formulasi XML yang baik (yaitu, benar secara sintaksis), tetapi secara semestinya salah.

Julian Reschke
sumber
11
Tentu saja ini adalah kode status HTTP, lihat iana.org/assignments/http-status-codes . Ada lebih banyak kode status daripada yang didefinisikan dalam RFC 2616.
Julian Reschke
7
WebDAV adalah ekstensi HTTP . "Ekstensi HTTP untuk Penulisan dan Versi Terdistribusi Web (WebDAV)" Jadi, kode status 422 bukan kode status http, tetapi kode status perpanjangan dari http.
deamon
16
Deamon, itu tidak masuk akal. HTTP mendefinisikan cara mendefinisikan kode baru, dan itulah yang dilakukan WebDAV. Ada kode registrasi status karena suatu alasan.
Julian Reschke
14
FYI - Deskripsi RFC dari 422: 11.2. 422 Entitas yang Tidak Dapat Diproses Kode status 422 (Entitas yang Tidak Dapat Diproses) berarti server memahami tipe konten entitas permintaan (oleh karena itu kode status 415 (Jenis Media yang Tidak Didukung) tidak pantas), dan sintaks entitas yang diminta benar (dengan demikian 400 (Status Buruk) kode status tidak sesuai) tetapi tidak dapat memproses instruksi yang terkandung. Misalnya, kondisi kesalahan ini dapat terjadi jika badan permintaan XML berisi formulasi XML yang baik (yaitu, benar secara sintaksis), tetapi secara semestinya salah.
Steve Kallestad
6
Dan utas tidak kedaluwarsa. Mereka harus dijaga agar tetap hidup atau hasil pencarian Google teratas mulai menjadi tidak akurat.
James Billingham
81

200.300, 400, 500 semuanya sangat generik. Jika Anda ingin generik, 400 tidak apa-apa.

422 digunakan oleh semakin banyak API, dan bahkan digunakan oleh Rails di luar kotak.

Tidak peduli kode status mana yang Anda pilih untuk API Anda, seseorang akan tidak setuju. Tapi saya lebih suka 422 karena saya menganggap '400 + status teks' sebagai terlalu umum. Selain itu, Anda tidak memanfaatkan parser JSON-ready; sebaliknya, 422 dengan respons JSON sangat eksplisit, dan banyak informasi kesalahan dapat disampaikan.

Berbicara tentang respons JSON, saya cenderung untuk membakukan pada respons kesalahan Rails untuk kasus ini, yaitu:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

Format ini sempurna untuk validasi formulir, yang saya anggap sebagai kasus paling rumit untuk didukung dalam hal 'kekayaan pelaporan kesalahan'. Jika struktur kesalahan Anda adalah ini, kemungkinan akan menangani semua kebutuhan pelaporan kesalahan Anda.

sethcall
sumber
2
Bagaimana dengan kesalahan yang timbul dari interaksi di antara argumen. Yaitu, arg1valid dan arg2valid, tetapi kombinasi keduanya, dengan nilai spesifik yang dikirim, tidak valid.
Jonah
1
Saya tidak akan terlalu memikirkannya; pilih saja yang tampaknya memiliki hubungan.
sethcall
atau bahkan hanya kesalahan pada kedua args. Sebagai pengguna, saya pikir saya ingin melihat kesalahan pada masing-masing bidang yang saling bertentangan, saya pikir.
Meringkuk
Bagus!. eksplisit lebih baik daripada implisit
bhathiya-perera
46

200

Ugh ... (309, 400, 403, 409, 415, 422) ... banyak jawaban yang mencoba menerka, memperdebatkan dan membakukan apa kode pengembalian terbaik untuk permintaan HTTP yang berhasil tetapi panggilan REST gagal. .

Adalah salah untuk mencampur kode status HTTP dan kode status REST.

Namun, saya melihat banyak implementasi yang memadukannya, dan banyak pengembang mungkin tidak setuju dengan saya.

Kode pengembalian HTTP terkait dengan HTTP Requestitu sendiri. Panggilan REST dilakukan menggunakan permintaan Hypertext Transfer Protocol dan berfungsi pada tingkat yang lebih rendah daripada metode REST yang dipanggil itu sendiri. REST adalah konsep / pendekatan, dan outputnya adalah hasil bisnis / logis , sedangkan kode hasil HTTP adalah transportasi .

Misalnya, mengembalikan "404 Tidak ditemukan" ketika Anda memanggil / pengguna / bingung, karena itu dapat berarti:

  • URI salah (HTTP)
  • Tidak ada pengguna yang ditemukan (REST)

"403 Dilarang / Akses Ditolak" dapat berarti:

  • Diperlukan izin khusus. Browser dapat menanganinya dengan menanyakan pengguna / kata sandi. (HTTP)
  • Izin akses yang salah dikonfigurasi di server. (HTTP)
  • Anda perlu diautentikasi (REST)

Dan daftar tersebut dapat berlanjut dengan '500 Server error "(kesalahan Apache / Nginx HTTP dilemparkan atau kesalahan kendala bisnis di REST) ​​atau kesalahan HTTP lainnya dll ...

Dari kode, sulit untuk memahami apa yang menjadi alasan kegagalan, kegagalan HTTP (transportasi) atau kegagalan REST (logis).

Jika permintaan HTTP berhasil dilakukan secara fisik, ia harus selalu mengembalikan 200 kode, terlepas dari apakah catatan ditemukan atau tidak. Karena sumber daya URI ditemukan dan ditangani oleh server HTTP. Ya, itu mungkin mengembalikan set kosong. Apakah mungkin untuk menerima halaman web kosong dengan 200 sebagai hasil HTTP, kan?

Alih-alih ini, Anda dapat mengembalikan 200 kode HTTP dengan beberapa opsi:

  • "error" objek dalam hasil JSON jika terjadi kesalahan
  • Kosongkan array / objek JSON jika tidak ada catatan yang ditemukan
  • Bendera hasil / keberhasilan bool dalam kombinasi dengan opsi sebelumnya untuk penanganan yang lebih baik.

Juga, beberapa penyedia internet dapat mencegat permintaan Anda dan mengembalikan Anda kode HTTP 404. Ini tidak berarti bahwa data Anda tidak ditemukan, tetapi ada sesuatu yang salah pada tingkat transportasi.

Dari Wiki :

Pada Juli 2004, penyedia telekomunikasi Inggris BT Group menyebarkan sistem pemblokiran konten Cleanfeed, yang mengembalikan kesalahan 404 untuk setiap permintaan konten yang diidentifikasi berpotensi ilegal oleh Internet Watch Foundation. ISP lain mengembalikan kesalahan HTTP 403 "dilarang" dalam keadaan yang sama. Praktek mempekerjakan 404 kesalahan palsu sebagai cara untuk menyembunyikan sensor juga telah dilaporkan di Thailand dan Tunisia. Di Tunisia, di mana sensor sangat keras sebelum revolusi 2011, orang-orang menjadi sadar akan sifat kesalahan 404 palsu dan menciptakan karakter imajiner bernama "Ammar 404" yang mewakili "sensor tak terlihat".

Kenapa tidak jawab saja dengan sesuatu seperti ini?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

Google selalu mengembalikan 200 sebagai kode status di Geocoding API mereka, meskipun permintaan gagal secara logis: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes

Facebook selalu mengembalikan 200 untuk permintaan HTTP yang berhasil, bahkan jika permintaan REST gagal: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling

Sederhana, kode status HTTP adalah untuk permintaan HTTP. REST API adalah milik Anda, tentukan kode status Anda.

Marcodor
sumber
3
Sebenarnya, menggunakan kode status HTTP untuk REST bahkan lebih membingungkan: 1) Anda melihat 4xx di kotak alat pengembang Anda dan Anda tidak bisa mengatakan hanya dengan melirik apakah server mengembalikan nilai yang masuk akal atau gagal memproses permintaan Anda sama sekali dan kemudian 2) semua penangan kesalahan / pengecualian / tangkapan Anda harus memeriksa server apa yang dikembalikan sebagai respons (kebanyakan mereka tidak melakukannya karena Anda harus melakukannya pada setiap panggilan layanan) dan berkali-kali 3) Anda mendapatkan muatan yang sama ( ketik) pada jalur keberhasilan dan kesalahan yang mengarah ke kode yang rumit / duplikat ... Memang sangat membingungkan.
szczepanpp
9
Jawaban ini membingungkan semantik asli protokol HTTP vs bagaimana REST over HTTP sebagai gaya arsitektur re-purpose HTTP untuk mengimplementasikan API layanan web. Sebagai gaya arsitektur, REST bukanlah standar yang harus diikuti dengan ketat, itu adalah pendekatan yang disarankan. Menggunakan respons 200 untuk kegagalan validasi tidak benar atau salah, namun membingungkan bagi klien Anda untuk merespons bahwa permintaan berhasil, tetapi sebenarnya gagal karena kegagalan validasi, detail penting yang dikaburkan dalam tubuh respons, semantik yang harus diuraikan oleh klien untuk dipahami.
Kevin Hooke
5
@Marcodor jika panggilan API Anda gagal tetapi Anda mengembalikan 200 yang mengindikasikan keberhasilan, bagaimana ini ide yang bagus? itu tidak jelas dan membingungkan bagi konsumen API Anda.
Kevin Hooke
3
Benar karena berbagai alasan, bukan hanya pemisahan kesalahan HTTP vs REST. Validasi REST seringkali membutuhkan lebih banyak nuansa. Misalnya, catatan diterima tetapi ditandai sebagai duplikat vs. ditolak karena pelanggaran indeks unik. Anda juga menginginkan model pengembalian yang konsisten. BadRequest()Metode .NET memiliki model pengembalian sendiri yang akan berbeda dari model pengembalian reguler Anda. Itu mimpi buruk untuk diurai. @KevinHooke, mengembalikan HTTP 200 untuk kesalahan validasi REST seperti mengatakan, "Saya menerima pesan Anda, jawabannya tidak, dan inilah sebabnya." Mengembalikan HTTP 400 mengatakan, "Saya tidak tahu apa yang Anda bicarakan."
Neil Laslett
5
argumen "karena google yang melakukannya, itu pasti benar" itu gila bagiku..tidak apa-apa untuk menantang sesuatu yang telah diterapkan anak-anak oleh google. Mengembalikan HTTP 200 untuk panggilan istirahat yang gagal membingungkan penelepon API itu harus 4xx dan orang dapat menyertakan JSON / XML yang cantik di dalam tubuh ... mari kita hentikan kegilaan bersama.
Jeryl Cook
43

Duplikat dalam database harus a 409 CONFLICT.

Saya sarankan menggunakan 422 UNPROCESSABLE ENTITYuntuk kesalahan validasi.

Saya memberikan penjelasan lebih lama tentang kode 4xx di sini .

Phil Parker
sumber
6

Kode Status 304 Tidak Dimodifikasi juga akan membuat respons yang dapat diterima untuk permintaan duplikat. Ini mirip dengan memproses tajuk If-None-Matchmenggunakan tag entitas.

Menurut pendapat saya, jawaban @ Piskvor adalah pilihan yang lebih jelas untuk apa yang saya rasakan adalah maksud dari pertanyaan awal, tetapi saya memiliki alternatif yang juga relevan.

Jika Anda ingin memperlakukan permintaan duplikat sebagai peringatan atau pemberitahuan alih-alih sebagai kesalahan, kode status respons 304Tidak Dimodifikasi danContent-Location tajuk yang mengidentifikasi sumber daya yang ada akan sama validnya. Ketika tujuannya hanya untuk memastikan bahwa ada sumber daya, permintaan duplikat tidak akan menjadi kesalahan tetapi konfirmasi. Permintaannya tidak salah, tetapi hanya berlebihan, dan klien dapat merujuk ke sumber daya yang ada.

Dengan kata lain, permintaan itu baik, tetapi karena sumber daya sudah ada, server tidak perlu melakukan pemrosesan lebih lanjut.

Suncat2000
sumber
6
Saya memahami bahwa 304 dimaksudkan untuk operasi GET untuk membantu dengan caching.
Sinaesthetic
6

Adaptor ActiveRecord Ember-Data berharap 422 UNPROCESSABLE ENTITYuntuk dikembalikan dari server. Jadi, jika klien Anda ditulis dalam Ember.js, Anda harus menggunakan 422. Hanya kemudian DS.Errors akan diisi dengan kesalahan yang dikembalikan. Tentu saja Anda dapat mengubah 422 ke kode lain di adaptor Anda.

Daniel Kmak
sumber
0

406 - Tidak Dapat Diterima

Yang berarti respons ini dikirim ketika server web, setelah melakukan negosiasi konten berbasis server, tidak menemukan konten yang sesuai dengan kriteria yang diberikan oleh agen pengguna.

Hasan Sefa Ozalp
sumber