Formulir AJAX mengharapkan JSON tetapi menerima HTML: telusuri respons langkah demi langkah
Respons 200 bukan bukti bahwa isinya JSON. Telusuri panel Network langkah demi langkah dan pisahkan kegagalan transportasi, representasi, dan kontrak.
Formulir terkirim, indikator muncul, dan konsol mengatakan ada token < tak terduga di JSON pada posisi 0. Halamannya sendiri termuat dengan baik, jadi naluri pertama adalah menyalahkan parser atau terowongan. Biasanya keduanya tidak terlibat: pengiriman adalah permintaan yang berbeda dari pemuatan halaman, dan ia kembali dengan sesuatu yang bukan JSON. Bekerjalah dalam urutan yang benar-benar diungkapkan peramban, karena empat kemungkinan jawaban menuntut empat perbaikan berbeda.
Langkah 1: tangkap pengiriman yang benar-benar terjadi
Buka panel Network sebelum mengirim, setel log untuk menyimpan entri antar navigasi, lalu lakukan satu pengiriman uji yang tidak berbahaya pada akun yang boleh Anda gunakan. Pilih permintaan yang dipicu formulir itu sendiri, bukan permintaan dokumen halaman.
Hati-hati dengan filter. Filter XHR atau Fetch memang nyaman, tetapi jika kerangka masih mengirim lewat iframe tersembunyi atau formulir yang dibuat dinamis, filter akan menyembunyikan satu-satunya permintaan yang penting. Kirim sekali tanpa filter lebih dulu dan lihat apa yang muncul.
Untuk permintaan yang dipilih, catat enam hal sebelum menafsirkan apa pun: metode, URL lengkap beserta string kueri, status, rantai pengalihan, Content-Type respons, dan baris pertama badannya. Referensi panel Network Chrome DevTools mencakup tampilan Headers, Response, dan Initiator tempat hal-hal itu berada, dan panel serupa di peramban lain menampilkan bidang yang sama.
Langkah 2: pastikan itu permintaan yang Anda maksud
Sejumlah besar kesalahan JSON sebenarnya adalah kesalahan perutean. Jika pengendali pengiriman melempar pengecualian sebelum memanggil preventDefault, peramban melakukan POST formulir asli ke alamat yang disebut atribut action, dan server menjawab dengan halaman HTML penuh. Pengendali tidak pernah berjalan, jadi JSON tidak pernah diminta.
Bandingkan URL di panel dengan URL yang dipanggil JavaScript Anda. Cari pengalihan yang berakhir di tempat lain, garis miring akhir yang hilang atau berlebih, ketidakcocokan metode ketika pengendali mengirim GET dan titik akhir menerima POST, atau formulir yang mengirim ke jalur relatif dari halaman yang telah pindah. Ikuti rantai pengalihan sampai akhir dan catat URL terakhir, bukan yang pertama.
Lalu periksa pemrakarsa. Jika permintaan datang dari navigasi dokumen dan bukan dari skrip Anda, Anda sudah menemukan masalahnya, dan tidak ada perubahan pada parser respons yang akan menolong.
Langkah 3: golongkan hasil ke dalam empat kategori
Setiap hasil termasuk tepat satu dari ini, dan kategorinya menentukan ke mana Anda melihat berikutnya.
| What you see | Category | Where to look |
|---|---|---|
| Request never finishes, TLS or connection error | No usable response | Endpoint reachability, certificate, front-end timeout |
| Request completes, script gets an opaque failure | Access blocked | Cross-origin policy, credentials mode, missing response header |
| 200 with an HTML body or a login form | Wrong representation | Redirect, expired session, route fallback, error handler |
| Body begins with a notice then valid JSON | Wrong representation | Server-side warning output before serialisation |
| Valid JSON, framework rejects it | Contract mismatch | Envelope shape, field names, value types |
Baris tengah adalah yang paling sering salah didiagnosis, karena statusnya 200. Halaman masuk yang dicapai setelah pengalihan adalah respons HTTP yang sangat baik sekaligus dokumen JSON yang sangat buruk. Jenis konten application/json tidak memperbaikinya: itu hanya label, dan badan yang salah label tetap gagal diurai. Akses diblokir adalah baris yang tampak seperti permintaan selesai: panel menampilkan status, tetapi kebijakan lintas asal menahan badannya, sehingga bagi skrip pemanggil ia sama tidak terpakainya dengan batas waktu.
Baris keempat sama umumnya pada tumpukan PHP dan kerangka lama. Peringatan penghentian pemakaian yang dicetak sebelum muatan terenkode menghasilkan badan yang tidak akan diterima parser JSON mana pun, dan sering kali peringatan itulah seluruh penjelasannya.
Langkah 4: baca kesalahan parser secara harfiah
Teks kesalahan menyebut karakter pertama yang mematahkan penguraian, dan itu biasanya mengenali kategorinya tanpa perlu menebak.
| Error text (Chrome/V8) | What it means |
|---|---|
| Unexpected token < in JSON at position 0 | The body starts with markup: an HTML page or an error document |
| Unexpected end of JSON input | Empty body, or the response was truncated |
| Unexpected token o in JSON at position 1 | You parsed something already parsed, typically an object rather than text |
| Unexpected token u | The body starts with the bare word undefined, usually an empty response rendered as a string |
Badan kosong dengan 200 adalah kasus tersendiri: titik akhir berjalan, tidak menghasilkan apa pun, dan sesuatu di hilir menganggapnya berhasil. Itu kegagalan kontrak aplikasi, bukan kegagalan transportasi, dan tempatnya di langkah berikutnya, bukan di proxy. Firefox dan Safari merumuskan empat kegagalan yang sama dengan cara berbeda, jadi cocokkan pada karakternya atau pada badan kosong, bukan pada string persisnya.
Langkah 5: perbaiki lapisan yang ditunjuk bukti
Untuk masalah perutean, perbaiki permintaannya: benarkan action, cegah pengendali jatuh, selaraskan titik akhir dan metode, lalu uji ulang. Untuk masalah representasi, perbaiki apa yang menghasilkan badan itu, dan cari tahu mengapa dokumen kesalahan dikembalikan di tempat yang diharapkan data. Untuk masalah kontrak, baca struktur sebenarnya yang diharapkan kerangka untuk versi yang Anda jalankan, dan bentuk respons sesuai itu alih-alih melonggarkan klien.
Respons dengan akses diblokir memerlukan giliran sendiri, karena permintaannya bisa benar dan badannya mungkin tidak pernah mencapai kode Anda. Bandingkan Access-Control-Allow-Origin respons dengan Origin persis yang dikirim peramban, dan ingat bahwa wildcard tidak memenuhi permintaan berkredensial. Pasangkan credentials: 'include' di klien dengan Access-Control-Allow-Credentials: true di server, dan periksa apakah panggilan memakai mode no-cors, tempat badan buram adalah hasil yang didokumentasikan, bukan cacat.
Mengganti parser dengan sesuatu yang lebih longgar adalah satu-satunya perbaikan yang harus dihindari. Mengevaluasi respons sebagai kode, atau mengupas teks sampai bisa diurai, menyembunyikan ketidakcocokan kontrak dan menambah permukaan injeksi sebagai ganti kesunyian. Sama pentingnya, status harus diperiksa terpisah dari badan: 200 yang membawa objek kesalahan tingkat aplikasi adalah normal di banyak API dan harus ditangani dengan membaca muatannya.
Ketika Anda butuh bantuan orang lain, bagikan catatan minimal — metode, URL, status, URL akhir setelah pengalihan, jenis konten respons, bentuk badan, dan kontrak yang diharapkan — alih-alih ekspor mentah. Arsip jaringan memuat cookie, token, string kueri, dan data pribadi yang ada di formulir, dan pembersih otomatis bukanlah tinjauan.
- Tangkap permintaan tanpa filter sebelum mengubah kode apa pun.
- Pastikan pemrakarsa adalah skrip Anda dan URL akhir adalah titik akhir Anda.
- Golongkan respons sebelum menyentuh parser.
- Perbaiki perutean, akses, representasi, atau kontrak, dan jangan pernah dengan melonggarkan parser.